Renzzauw
Renzzauw

Reputation: 17

Unity: Camera Collider

I'm creating a 3th person game for a school project but I am having some trouble with collisions: I have a player with a camera as a child that has a sphere collider. When the camera collides with any scenery objects such as houses, it should zoom out. Once it leaves the collision situation it should return to its old position (its local y should be 4.5). Now I am having the following problem when standing still: the camera constantly leaves and enters the object's collider which causes it to keep zooming in and out. This results in a really glitchy looking camera movement. Is there any way to solve this problem?

I used the following code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class CamMovement : MonoBehaviour
 {
     public GameObject Parent;

     //Checks if the camera collides with something
     void OnTriggerStay(Collider other)
     {
         //When colliding, the camera moves up and back from the player object          
         transform.position += new Vector3(0, 0.2f, -0.2f);    
     }


     void Update()
     {
         //makes sure the camera always looks at the player object   
         transform.LookAt(Parent.transform);

         //Moves the camera back to the normal (local) position
         if (transform.localPosition.y > 4.5f)
         {
             transform.position += new Vector3(0, Time.deltaTime * -4f, Time.deltaTime * 4f);
         }
     }
 }

Footage of what it looks like when the camera collides with something: https://i.sstatic.net/pIn9n.jpg

Upvotes: 0

Views: 8252

Answers (2)

ScottishTapWater
ScottishTapWater

Reputation: 4806

You need to check which collider is colliding with the camera collider, you could achieve this using a structure something like this in your OnColliderEnter(Collider other):

Collider playerCollider = GameObject.Fine("Player").GetComponent<Collider>();
if (!other == playerCollider)
{
//Do your zooming out.
}

Upvotes: 1

Kardux
Kardux

Reputation: 2157

Not sure if I understood what you want to achieve correctly but I'll give it a shot:

I think you should rather look into OnTriggerEnter and OnTriggerExit event so you can tell the Camera to move away when trigger is entered and move back when its exited.

public class CamMovement : MonoBehaviour
{
    //using "parent" as variable name is not recommended since Transform class already contains a parent variable
    [SerializeField]
    private GameObject parentToLookAt;
    [SerializeField]
    private Vector3 localPositionOffset;
    [Range(0.0f, 10.0f)]
    [SerializeField]
    private float transitionSpeed;

    private Vector3 localPositionOnStart;
    private bool applyOffset;

    void Start()
    {
        localPositionOnStart = transform.localPosition;
        applyOffset = false;
    }

    void Update()
    {
        //Makes sure the camera always looks at the player object
        //You can also use: transform.LookAt(transform.parent); 
        transform.LookAt(parentToLookAt.transform);

        //Moves the camera to the right local position (note that using Mathf.Lerp is not optimal performance-wise but if you want more info on this
        //I recommend looking for further informations at https://chicounity3d.wordpress.com/2014/05/23/how-to-lerp-like-a-pro/ )
        if (applyOffset)
        {
            transform.localPosition = Mathf.Lerp(transform.localPosition, localPositionOnStart + localPositionOffset, transitionSpeed * Time.deltaTime);
        }
        else
        {
            transform.localPosition = Mathf.Lerp(transform.localPosition, localPositionOnStart, transitionSpeed * Time.deltaTime);
        }
    }

    //Checks if the camera collides with something
    void OnTriggerEnter(Collider other)
    {
        applyOffset = true;
    }

    //Checks if the camera stops colliding with something
    void OnTriggerExit(Collider other)
    {
        applyOffset = false;
    }

    //You can also use this:
    //void OnTriggerStay(Collider other)
    //{
    //    applyOffset = true;
    //}
    // and set applyOffset to false at the end of the Update() method (OnTrigger events are called before Update each frame)
}

Two more things:

  • when programming in C# it's a common rule not to use a capital letter to start a variable name (this is reserved to class names): you can check here for global guidelines
  • also you can using [SerializeField] attribute to serialize a private variable (and therefor make it appear in the Inspector). I also added the [Range()] attribute which is useful when working with designers (they don't like raw numbers ;) )

Upvotes: 0

Related Questions