CTIN 289 - Interactive Snippets Library

Powered by 🌱Roam Garden

Security Camera

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


/* This class moves the camera part of the security camera model
 * so that it stays pointed at the little car as it races around.
 * Note that it will only follow the car when the car is visible,
 * i.e. not behind a block.
 * 
 * There is some complicated rotation code, but all you need to 
 * understand is the raycasting that is happening in FixedUpdate.
 */

public class SecurityCamera : MonoBehaviour
{

    [SerializeField]
    GameObject car;

    [SerializeField]
    float watchDistance;

    //note that I don't need a layer mask here
    //because the camera doesn't have a collider

    Transform swivel;
    Vector3 directionToTarget;

    void Start()
    {
        swivel = transform.Find("Camera/Swivel");
        //The camera model has two parts: the boxy camera
        //itself, and the structure that attaches it to
        //the wall.
        //I want the camera part to look back and forth
        //and the wall mount to stay in place.
    }



    void FixedUpdate()
    {
        directionToTarget = car.transform.position - transform.position;

        Debug.DrawRay(
            transform.position,
            directionToTarget.normalized * watchDistance,
            Color.red
        );

        RaycastHit rHit;
        //3D raycasts are weird because they use an "out"
        //parameter instead of just returning a value like
        //a normal method. This is both uncommon and frowned-upon.
        //You're unlikely to see it anywhere else in Unity.

        Physics.Raycast(
            transform.position,
            directionToTarget,
            out rHit,
            watchDistance
        );

        if (rHit.collider != null)
        {
            Debug.Log("Ray hit " + rHit.collider.name);

            //transform.root means "look all the way up the
            //hierarchy from this object until you find the
            //one that has no parent". In this case, traveling
            //up from the individual collider, like FrontRightWheel,
            //to SciFiCar_Prefab, to Car
            if (rHit.collider.transform.root.tag == "Car")
            {
                swivel.LookAt(car.transform.position);
                //This line tells the camera model to line up its
                //personal "forward" to point at the car. But it
                //doesn't quite work. Its parent GO SecurityCamera
                //is rotated by 90 degrees, so all of its children are
                //also rotated by 90 degrees. LookAt doesn't account
                //for this.

                swivel.rotation *= Quaternion.Inverse(transform.rotation);

                //So this line "undoes" (offsets) the SecurityCamera
                //GameObject's rotation. Comment out the line to
                //see what it's doing.

                //Also, be aware that this is pretty advanced! It took
                //me a few tries to find a solution. But it's a useful
                //technique, as well as an illustration of how rotation
                //gets complicated quickly.

                //Credit to
                //https://answers.unity.com/questions/950010/offset-lookat-rotation.html

            }
        }
    }
}