I had the same Sci Fi game prototype and on my laptop i had the main character using LE3 character controller becoming very unresponsive with long deceleration and too slow accelerations when using faster movement speed.
I thaught it was the level complexity or the laptop , because it runs just good on a powerfull machine.
I made my own character controller, with it's own deceleration system and surprise there is no lagging physics and quick custom deceleration , unlike LE3 default character controller on the same map level in my laptop
1) I use a 3d detailled sphere model as the moving 3D object , so there is no friction problems
2) It works and physics stay constant with PhysicsUpdate , no deceleration lag or slow accelerations using my own deceleration system
3) Using higher movement speed, there is no collision problems or pass through and there is no lagging or long deceleration problems or slow acceleration
So my question is should LE3 character controller need to be re worked for other people that can't code their own ?
Or should it be added some other character controller for faster character games movement ?
For people interested here is the work in progress code , it is not final as deceleration must be tweaked to be proportionnal to character speed.
Speed directions and axe rotation are really specific to direction keys for some game specific gameplay, so it is not some totally general usage controller.
Also it needs a really detailled and smooth sphere model to work good.
This is also non optimized code but this gives you some hints on how it works.
Script.character = "" --entity
Script.smoothness = 5000--int
--Script.camera = "" --entity
function Script:Start()
self.playerMovement = Vec3(0,0,0)
self.moveSpeed = 30
self.speedAutoDirection = 0.05
self.entity:SetFriction(0.5,0.5)
self.maxSpeed = 25
self.angleDir = 0
self.dirPrevFrame = self.entity:GetPosition(true)
self.posFrame = self.entity:GetPosition(true)
self.deltaPosTime = Time:Millisecs()
self.prevRot = Vec3(0,0,0)
self.direction = Vec3(0,0,0)
end
function Script:UpdateWorld()
self.posFrame = self.entity:GetPosition(true)
dirSmooth = Vec3(0,0,0)
--dirSmooth.x = Math:Curve(self.posFrame.x, self.dirPrevFrame.x,30)
newCharPos = Vec3(0,0,0)
dirSmooth.x = (self.posFrame.x - self.dirPrevFrame.x) / 2
dirSmooth.z = (self.posFrame.z - self.dirPrevFrame.z) / 2
newCharPos.z = Math:Curve(self.dirPrevFrame.z,self.posFrame.z,self.smoothness/Time:GetSpeed())
newCharPos.x = Math:Curve(self.dirPrevFrame.x,self.posFrame.x,self.smoothness/Time:GetSpeed())
newCharPos.y = Math:Curve(self.dirPrevFrame.y,self.posFrame.y,self.smoothness/Time:GetSpeed())
self.character:SetPosition(newCharPos,true)
local angle = -Math:ATan2(dirSmooth.z,-dirSmooth.x)
angle3 = Vec3(0,angle-90,0)
self.character:SetRotation(angle3,true)
end
function Script:UpdatePhysics()
rotation = self.entity:GetRotation(true)
self.posFrame = self.entity:GetPosition(true)
if Time:Millisecs()- self.deltaPosTime > 300 then
self.deltaPosTime = Time:Millisecs()
self.dirPrevFrame = self.posFrame
end
--self.direction = ( self.posFrame - self.dirPrevFrame ):Normalize()
speedX = ((App.window:KeyDown(Key.D) and 1 or 0) - (App.window:KeyDown(Key.A)and 1 or 0))
speedY = ((App.window:KeyDown(Key.Z) and 1 or 0) - (App.window:KeyDown(Key.W)and 1 or 0))
self.playerMovement.x = speedX * Time:GetSpeed() * self.moveSpeed
self.playerMovement.z = speedY * Time:GetSpeed() * self.moveSpeed
vect = Vec3(speedX,0,speedY):Normalize()
vel = self.entity:GetVelocity(true)
if vel.x > self.maxSpeed and speedX == 1 then
vel.x = self.maxSpeed /3
self.playerMovement.x = 0
end
if vel.x < -self.maxSpeed and speedX == -1 then
vel.x = -self.maxSpeed /3
self.playerMovement.x = 0
end
if vel.z > self.maxSpeed then
vel.z = self.maxSpeed /3
self.playerMovement.z = 0
end
if vel.z < -self.maxSpeed then
vel.z = -self.maxSpeed /3
self.playerMovement.z = 0
end
if vel.x > self.speedAutoDirection and speedX == 0 then
self.playerMovement.x = -self.speedAutoDirection * Time:GetSpeed() * self.moveSpeed *3
end
if vel.x < self.speedAutoDirection and speedX == 0 then
self.playerMovement.x = self.speedAutoDirection * Time:GetSpeed() * self.moveSpeed *3
end
if vel.z > self.speedAutoDirection and speedY == 0 then
self.playerMovement.z = -self.speedAutoDirection * Time:GetSpeed() * self.moveSpeed *3
end
if vel.z < self.speedAutoDirection and speedY == 0 then
self.playerMovement.z = self.speedAutoDirection * Time:GetSpeed() * self.moveSpeed *3
end
--self.entity:AddForce(direction * Time:GetSpeed() * self.moveSpeed,true)
self.entity:AddForce(self.playerMovement,true)
--self.entity:AddForce( direction * Time:GetSpeed() * self.moveSpeed , true)
if speedX == 0 and speedY ==0 then
--self.entity:AddForce(vel,true)
vel = vel*-1 *15
self.entity:AddForce(vel,true)
end
end