- Home /
Alternative to character controller? (Multiple CCs are mangling my framerate)
I've got a scene with about 200 NPCs in it. Each one has an example script attached to afford 'random' movement (courtesy of a Unity forum user):
var ground: Transform; var gravity: Vector3; var speed: float;
var motionDir: Vector3; var ctrl: CharacterController;
function Start() { ctrl = GetComponent(CharacterController); NewDirection(); }
function Update () { ctrl.Move((motionDir speed + gravity) Time.deltaTime); }
function OnControllerColliderHit(collision: ControllerColliderHit) { if (collision.transform != ground) { NewDirection(); } }
function NewDirection() { motionDir = (new Vector3(Random.value - 0.5, 0.0, Random.value - 0.5)).normalized; transform.rotation = Quaternion.LookRotation(motionDir); }
There's a problem! Each NPC needs a Character Controller for this script to reference...but with 200 in the scene at once, play slows to a crawl. For a code noob: is there a less computationally-draining alternative to the Character Controller out there somewhere? Or, any suggestions for a script that produces similar results to this without needing a Character Controller?
Answer by Jaap Kreijkamp · Dec 12, 2009 at 02:02 AM
Consider having NPCs outside the players view disabled.
Answer by Ricardo · Dec 12, 2009 at 02:51 AM
It depends on what you're trying to get the character to do. Could you give more details?
If what you're looking for are steering algorithms to drive your characters, you could look into UnitySteer. However, depending on your level of experience, building up a controller from the various algorithms in the toolkit might seem complex.
Update: I just noticed that you're updating every character, every frame. Is that really necessary? You could have a round-robin mechanism where you only update a few objects per frame.
It's actually simpler than it sounds: the 'NPCs' are capsules - with no animation - and I just want them to be able to run around, in any direction, avoiding or circumventing obstacles. The behaviour doesn't have to be complex at all. I was recommended UnitySteer before, but it did seem quite complex. I'll check that out again.
As for my level of experience; I'm afraid it's low. I'm learning as I go, but writing my own scripts from scratch is still a long way off =(
Answer by Brian-Kehrer · Dec 12, 2009 at 04:20 AM
This is a problem best solved with code, or changing the problem.
Your best option is not having 200 characters in the scene, obviously.
Alternatively, it may be the Move() function is causing most of the slowdown, not the characterController itself. You can determine this in the profiler.
If that is the case, you could only call Move() on the characters that actually need to be moving, instead of on all 200 at once. Have the AI determine when a character should move, and only then call Move().
If this is some epic battle with 200 people running around - I don't think there will be a simple solution, your best bet is to start learning about the physics system, raycasts, triggers and so on.
It's by no means an epic battle ;) I do really need all 200 onscreen at once, though. The idea of the game is to 'herd' these simple NPCs in ever-increasing numbers for big scores, so it's all about the quantity.
I'd give the Profiler a go, but I'm working with vanilla Unity. Is $$anonymous$$ove() notoriously problematic?
Answer by Ricardo Arango · Jun 16, 2010 at 06:24 PM
One simple optimization you can do to that script:
Store this value (motionDir * speed + gravity) in a Vector3, and update it only when "motionDir" or "speed" change.
So your code can be:
function Update () { ctrl.Move(motionVector * Time.deltaTime); }
function NewDirection() { motionDir = (new Vector3(Random.value - 0.5, 0.0, Random.value - 0.5)).normalized; motionVector = motionDir * speed + gravity; transform.rotation = Quaternion.LookRotation(motionDir); }