Camera & Sphere Collider

I'm trying to get a sphere collider working with my camera and the terrain without success. So far I've tried attaching a sphere collider + rigidbody, collider, toggling IsTrigger in both cases, etc... the problem is that when the cameras collider hits the terrain it never seems to trigger a OnCollisionEntry or OnTriggerEntry (I'm overriding both to try and catch the event).

I have even just tossed debug output to see that the collider is moving with the camera, etc... all seems well, I'm not sure what the issue is here.

Any ideas how to make a camera collider work with terrain?

Edit: Added Camera Control Script Code.

enum Axis {MouseXandY, MouseX, MouseY}
var Axis : Axis = Axis.MouseXandY;

var sensitivityX = 15.0;
var sensitivityY = 15.0;

var minimumX = -360.0;
var maximumX = 360.0;

var minimumY = -60.0;
var maximumY = 60.0;

var rotationX = 0.0;
var rotationY = 0.0;

var lookSpeed = 2.0;

function OnTriggerEnter (other : Collider) 
{
    print( "OTE" );
}

function OnCollisionEnter(collision : Collision) 
{
    print( "OCE" );
}

function Update ()
{
    // allow for WSAD control of the camera     
    var x = Input.GetAxis( "Horizontal" ) * Time.deltaTime * 10.0; 
    var z = Input.GetAxis( "Vertical" ) * Time.deltaTime * 10.0; 
    transform.Translate ( x, 0, z );    

    // handle mouse look, only mouse look when right mouse button is used
    if( Input.GetMouseButton( 1 ) ) 
    {
        // Read the mouse input axis
        rotationX += Input.GetAxis( "Mouse X" ) * sensitivityX;
        rotationY += Input.GetAxis( "Mouse Y" ) * sensitivityY;
        // Call our Adjust to 360 degrees and clamp function
        Adjust360andClamp();
        transform.localRotation = Quaternion.AngleAxis( rotationX, Vector3.up );
        transform.localRotation *= Quaternion.AngleAxis( rotationY, Vector3.left );
    }
}

function Adjust360andClamp ()
{
    // Don't let our X go beyond 360 degrees + or -
    if (rotationX < -360)
    {
        rotationX += 360;
    }
    else if (rotationX > 360)
    {
        rotationX -= 360;
    }   

    // Don't let our Y go beyond 360 degrees + or -
    if (rotationY < -45)
    {
        rotationY = -45;
    }
    else if (rotationY > 30)
    {
        rotationY = 30;
    }

    // Clamp our angles to the min and max set in the Inspector
    rotationX = Mathf.Clamp (rotationX, minimumX, maximumX);
    rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
}

Not sure if this question is still active, but I thought I'd try my hand at an answer. I'm relatively new to Unity, so I'm no authority on this, but I also found the collision docs somewhat ambiguous on this subject.

I can't divine the exact problem from only the details provided above so I will provide an alternate solution to using the built-in physics. I recommend you still learn the physics stuff if only for your own benefit, rather than simply taking my rough solution below by itself.

Some stuff that might help with the physics stuff

See the manual. The collision matrix should be informative.

And note the line, "Be aware that in order for two Triggers to send out trigger events when they collide, one of them must include a Rigidbody as well. For a Trigger to collide with a normal Collider, one of them must have a Rigidbody attached."

Also, when your camera has a rigidbody, is IsKinematic checked?

One solution that'll do in a pinch

Do a simple ray/line cast against only the things you care to collide with (not the camera's collider if you have one). With this solution, your camera needn't have a collider or rigidbody if you don't want them.

You should pragma strict your unityscript to cut the overhead of dynamic typing.

This is quick and untested code, but something like:

var hitInfo : RaycastHit;
var layersToCollide : int = 1<<9; //Collide with layer 9
var buffer : float = 10; //Find a value that works for you

function Update ()
{
    // allow for WSAD control of the camera     
    var x : float = Input.GetAxis( "Horizontal" ) * Time.deltaTime * 10.0; 
    var z : float = Input.GetAxis( "Vertical" ) * Time.deltaTime * 10.0; 

    var destination : Vector3 = Vector3(x,0,y) + transform.position;

    if (Physics.Linecast (transform.position, destination, hitInfo, layersToCollide)) {
        //If it helps, you may want to debug with Debug.DrawLine(transform.position, hitInfo.point);
        //Just a quick example, but you may want to do some correction like:
        var distance : float = hitInfo.distance - buffer;
        var correction : Vector3 = Vector3.Normalize(x,0,y) * distance;
        destination = transform.position + correction;

        ///Whatever else you wanted to do on collision
    }

    transform.position = destination;

    ///Other stuff
}

This may be a very simple albiet weird answer to your problem... try using a charcter controller and try to "move" it to the target position instead of directly forcing it to a location with "translate". You could use a rigidBody and move a constraint, but this can be tricky, and you might get Roll and spring-back reactions. The manual says that character controllers are very efficient, so using them like this shouldn't be too harmful. I don't think that directly moving any colliders to intersect (whether they have rigid bodies or not), will necessarily register a collision and there is likely your first problem thus far.

Could you post your code? First thing that comes to mind is that the functions are called OnCollisionEnter() and OnTriggerEnter not entry. Another problem could be the way you move the camera, as for example transform.Translate won't trigger the physics (and therefore collisions).

Have you tried using OnTriggerStay? You do need a non-kinematic rigidbody on one of the objects, either the camera or the wall (probably better on the camera) You can also try using the isVisible value to make the camera check if the player is visible and then move closer if he isn't.

Not knowing the reason for using a collider on the camera, assuming the colliding camera is a solution to the problem of the camera dropping under the terrain, I'd avoid the issue altogether. Collider, or even a raycast is overkill.

If it's just a matter of keeping it above the terrain, I'd just check the height of the terrain (Terrain.SampleHeight) directly; whenever the camera got too close I'd override the user input from my script and force the camera to translate to SampleHeight+1.

I experienced the problem while trying to prevent a follow camera from rotating such that you can see straight through my terrain. In the unity forums there is a post that discusses it. The solution we determined was to us a raycast behind the player and do constrain camera rotation if it reached a certain point where there was a "collision" of the terrain with the raycast

I’m not sure if this helps or if this thread is going still or not, but I tried something similar starting with the “mouseOrbit” script. I attached a rigidbody and a sphere collider to the camera and set the target to be a tree on top of a flat terrain.
Then I added the OnCollisionEnter part to the script.

Sure enough, the collider does indeed register collisions with terrain and prints “OCE” onto the console.

I think part of the problem with the camera control scripts is that it they are using “transform.translate” to do the work of moving the camera. I’m still very new to unity, but I believe that this is akin to “teleporting” the location of the camera. I.e. the script is setting the camera position to a new location directly. So, there is no chance for rigid body interaction physics.

To get physics based collisions, motion would need to be controlled using “rigidbody.AddForce” wouldn’t it?

Anyway, I tried using your script, but moving your wasd control into fixed update and replacing “transform.translate” with “rigidBody.AddForce” I also added a drag of 0.1 onto the rigid body as well (to inhibit sliding):

function FixedUpdate ()
{
    // allow for WSAD control of the camera     
    var x = Input.GetAxis( "Horizontal" ) * 5.0; 
    var z = Input.GetAxis( "Vertical" ) * 5.0; 
    rigidbody.AddForce ( x, 0, z );  
} 

That seemed to do the trick… Of course, the camera is stuck in the Y plane it starts in or else falls to the ground and rolls along it. Is that what you were after?

The drag and force may need a bit of tweaking if you aren’t going to have the camera roll along terrain (where friction could be used instead).