SLOW PERFORMANCE on Transform.position

I’m really surprised and upset about this.
I have a collision detection and response routine and profiling it I found out that calling transform.position is internally calling get_position, and it’s taking a lot of CPU! Please note that I’m already caching the transform of all the colliders.
But calling .position on 2500 objects it’s taking more than all the actual collision resolution.
Is there any way around this?

Are you going by the profiler? Small operations like transform.position show up in the profiler because they are properties and not fields. I am not sure about unity’s profiler but i know most time based profilers can take fast calling methods that are called frequently show up alot more cpu heavy than they are.

I don’t know the internals of how the get and set works for transform, but if you have a huge hierarchy with alot of childs whenever you change a position, rotation, scale in a parent all the children get updated. I’m unsure if unity delays this calculation until its queried ( like not updating a childs transform.position internally until its requested ) or if unity actually updates children transforms immediately with parent changes. If they have anything similar to the first possibility this could be causing the delay if it is caused by the position property.

Are you doing this poll of all positions in FixedUpdate, Update, or LateUpdate? FixedUpdate gets called 50 times a second regardless of framerate, so its important to avoid using FixedUpdate except for fast executing code related to physics only. If FixedUpdate is too slow you’ll get a huge penalty in performance because it needs to catch up.

I’d suggest using LateUpdate if your going through a ton of objects. Assuming most transform changes are done in update i’d imagine heavy polling code would be faster.

Otherwise if its none of those things and had to guess whats causing CPU, is that you have 2500 objects that your polling every update ( fixed or not ). And if that is the case, I’d suggest that you either avoid declaring a update method or make use of .enabled which turns the calling of update/fixedupdate/lateupdate off.

What are you working on though? I can’t think of a situation where you’d need to check position of that many things constantly, but am interested to hear

Yes I’m using Unity profiler, and what you say makes sense.
Anyways the hierarchy is just 1 level (every object has a parent). I’m doing the poll in Update.
I’m just playing around with Unity and I created a demo with lots of moving spheres colliding. So every frame each sphere has to check the position of all the other spheres.

Here’s my ResolveCollision function:

protected void ResolveCollisions(CollisionSphere[] colliders, Vector3 targetPosition)
{
	float radius = mSphereCollider.radius;
	foreach (CollisionSphere collider in mOtherColliders)
	{
		if (collider.mTransform!=mTransform)
		{		
			Vector3 otherPos = collider.mTransform.position;
			float radiusSum = collider.mRadius + radius;
			if ((targetPosition-otherPos).sqrMagnitude<radiusSum*radiusSum)
			{	
				Vector3 constraintDirection = (targetPosition - otherPos).normalized;
				Vector3 constraintVec = constraintDirection*radiusSum;
				Vector3 errorVec = constraintVec - (targetPosition - otherPos);
				Vector3 newPosition = targetPosition+errorVec;
				float angle = Vector3.Angle(targetPosition, newPosition);
				Vector3 axis = Vector3.Cross(targetPosition, newPosition).normalized;
				Quaternion errorRotation = Quaternion.AngleAxis(angle, axis);
				mTransform.parent.rotation = errorRotation * mTransform.parent.rotation;
			}
		}
	}
}

The CollisionSphere array mOhterColliders is filled on the Start so that I have all the tranforms cached:

protected void Start ()
{
	SphereCollider[] colliders = FindObjectsOfType(typeof(SphereCollider)) as SphereCollider[];
	int numColliders = colliders.Length;
	mOtherColliders = new CollisionSphere[numColliders];
	int count = 0;
	foreach (SphereCollider sphere in colliders)
	{
		mOtherColliders[count].mTransform = sphere.transform;
		mOtherColliders[count].mRadius = sphere.radius;
		++count;
	}
}

I thought that maybe the access to

Vector3 otherPos = collider.mTransform.position;

was being slow because position is actually a call that goes through the hierarchy and calculates the position, so I tried to move ResolveCollisions from Update to LateUpdate, thinking that maybe after the update all positions are already calculated and cached, but it actually made everything slower!
So I’m clueless…

a few years later but I just found a possibile solution for a similar problem.
I had a rigidbody with lots of meshcollider attached and transgorm.position did the job in 88msec, inacceptable.
Simply replaced my “transform.position = position” call with “rigidbody.MovePosition(position)” and voilà, problem resolved!
By the way the way I also discovered that the right to move a GameObject with a rigidbody is with rigidbody.MovePosition() or rigidbody.position().
Hope this helps someone! :smile:

5 Likes

Thanks that solved it, I just disabled the rigidbody with “collider.enabled = false;”