Hello,
I’m having an interesting problem here and hoping someone has the expertise to help me out. I’m building a custom character controller for Unity, doing all of the physics collisions myself, detecting when objects collide by using the Physics.OverlapSphere method (using 3 or more of them to simulate a capsule shape) in the Update() call. This has worked well for colliding with static objects, but I’m starting to run into trouble now that I’m trying to implement moving objects (mostly moving platforms). Basically, you have two steps, both run in Update() methods of separate MonoBehaviors. A moving object has it’s transform.position updated, and the player character runs OverlapSphere to detect collisions. Let’s assume that the moving object is updated first (since this is desirable behavior and is easy to accomplish in theory by having a controller order all your objects Update calls).
The moving object is translated X units. We’ll also assume that before being translated, it is NOT colliding with the player, and after being translated, it IS. Now the player will run his OverlapSphere call, and in theory detect the moving object and run collision resolution and everything will be working correctly. The problem is this doesn’t actually work, since it seems that in Unity, a collider’s position isn’t actually updated until the physics are updated (?). OverlapSphere is kind of an odd function in that it lets you detect collisions outside of the main physics loop, so I’m not sure how it actually works. Either way, I wrote a quick script to test this:
using UnityEngine;
using System.Collections;
public class CollisionTest : MonoBehaviour {
public float Radius = 2.0f;
public Transform target;
void Start () {
}
Vector3 cache;
void Update () {
cache = target.position;
MoveTo();
DetectCollision();
target.position = cache;
}
void MoveTo()
{
Vector3 direction = transform.position - target.position;
target.position += direction;
}
void DetectCollision()
{
Collider[] cols = Physics.OverlapSphere(transform.position, Radius);
foreach (var col in cols)
{
Debug.Log(col.name);
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, Radius);
}
}
Target should be any object with a collider that is not touching the OverlapSphere before running. The target is moved on top of the sphere, collisions are run, and then it’s reset. Unfortunately no collisions are ever detected. Weirdly enough if you run it in Start it does detect collisions.
Is there any way to force the collider positions to update in the Update() call, before the physics timestep? Or any other solution to this problem?
Thanks,
Erik