x


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?

more ▼

asked Dec 11 '09 at 07:16 PM

zenislev gravatar image

zenislev
19 7 7 15

(comments are locked)
10|3000 characters needed characters left

5 answers: sort voted first

Consider having NPCs outside the players view disabled.

more ▼

answered Dec 12 '09 at 02:02 AM

Jaap Kreijkamp gravatar image

Jaap Kreijkamp
6.4k 20 26 70

(comments are locked)
10|3000 characters needed characters left

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.

more ▼

answered Dec 12 '09 at 02:51 AM

Ricardo gravatar image

Ricardo
5.2k 20 32 96

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 =(

Dec 12 '09 at 10:34 PM zenislev
(comments are locked)
10|3000 characters needed characters left

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.

more ▼

answered Dec 12 '09 at 04:20 AM

Brian Kehrer gravatar image

Brian Kehrer
2.8k 9 11 50

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 Move() notoriously problematic?

Dec 12 '09 at 10:35 PM zenislev
(comments are locked)
10|3000 characters needed characters left

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);
}
more ▼

answered Jun 16 '10 at 06:24 PM

Ricardo Arango gravatar image

Ricardo Arango
628 10 13 26

(comments are locked)
10|3000 characters needed characters left

It may not be the Character Controller see

http://forum.unity3d.com/viewtopic.php?t=39946

more ▼

answered Dec 23 '09 at 08:07 AM

bill gravatar image

bill
41 1 1 4

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x5072
x1043

asked: Dec 11 '09 at 07:16 PM

Seen: 4313 times

Last Updated: Dec 11 '09 at 07:16 PM