3
\$\begingroup\$

The doors open automatic when the player is getting close to them and then close when the player get some far distance from them.

Each door is built from door_right and door_left and I made that each door_right and door_left will be tagged as Waypoint.

Screenshot example of a door:

Door example

On the door there is a script that open/close the door: The script is attached to each door_right and door_left:

using UnityEngine;
using System.Collections;

public class DoorHori : MonoBehaviour {

    public float translateValue;
    public float easeTime;
    public OTween.EaseType ease;
    public float waitTime;

    private Vector3 StartlocalPos;
    private Vector3 endlocalPos;

    private void Start(){
        StartlocalPos = transform.localPosition;    
        gameObject.isStatic = false;
    }

    public void OpenDoor(){
        OTween.ValueTo( gameObject,ease,0.0f,-translateValue,easeTime,0.0f,"StartOpen","UpdateOpenDoor","EndOpen");
        GetComponent<AudioSource>().Play();
    }

    private void UpdateOpenDoor(float f){       
        Vector3 pos = transform.TransformDirection( new Vector3( 1,0,0));
        transform.localPosition = StartlocalPos + pos*f;

    }

    private void UpdateCloseDoor(float f){      
        Vector3 pos = transform.TransformDirection( new Vector3( -f,0,0)) ;

        transform.localPosition = endlocalPos-pos;

    }

    private void EndOpen(){
        endlocalPos = transform.localPosition ;
        StartCoroutine( WaitToClose());
    }

    private IEnumerator WaitToClose(){

        yield return new WaitForSeconds(waitTime);
        OTween.ValueTo( gameObject,ease,0.0f,translateValue,easeTime,0.0f,"StartClose","UpdateCloseDoor","EndClose");
        GetComponent<AudioSource>().Play();
    }
}

Next I have the Player and I want to move between the waypoints the Player: The Player is tagged as InstanceToMove:

Player

The Player have a camera:

Camera

And this is the Waypoints script attached to the GameObject name Waypoints:

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

public class Waypoints : UnityEngine.MonoBehaviour
{
    // Adding selectable behaviour at the end of the path,
    // as requested from the comments.
    public enum PathCompleteBehaviour
    {
        Stop,
        Loop,
        Reverse,
        Random,
        PingPong
    }
    [Header("Path Behaviour")]
    public PathCompleteBehaviour pathBehaviour;

    [Space(5)]

    [Header("Waypoints")]
    public GameObject[] waypoints;
    public float distanceFromWP = 1;

    [Space(5)]

    [Header("Instances")]
    public GameObject[] instancesToMove;

    [Space(5)]

    [Header("Speed")]
    public float constantSpeed;
    public float minRandomSpeed, maxRandomSpeed;
    public bool randomSpeed = false;
    private bool randoms = true;

    public bool go = false;

    // Store parallel arrays for our movement parameters.
    private float[] movementSpeeds;    // Randomized speed per object.
    private int[] nextWaypointIndices; // Destination per object.

    private void Start()
    {
        // Changing terminology to be more standard.
        // - a "prefab" is a source asset you want to copy
        // - an "instance" is a copy of it that's been spawned in the scene
        instancesToMove = GameObject.FindGameObjectsWithTag("InstanceToMove");

        waypoints = GameObject.FindGameObjectsWithTag("Waypoint");

        movementSpeeds = new float[instancesToMove.Length];
        nextWaypointIndices = new int[instancesToMove.Length];

        RandomSpeed();
    }

    private void Update()
    {
        if (randomSpeed == true)
            randoms = true;
        RandomSpeed();

        if (go)
            WaypointsAI();
    }

    private void WaypointsAI()
    {
        // We want to iterate over the instances, not over the waypoints.
        for (int i = 0; i < instancesToMove.Length; i++)
        {
            // Check to see if we reached the last waypoint.
            // If so, stop / loop / turn around as needed.
            int waypointIndex = nextWaypointIndices[i];
            if (waypointIndex < 0 || waypointIndex >= waypoints.Length)
            {
                switch (pathBehaviour)
                {
                    case PathCompleteBehaviour.Stop:
                        // Leave it where it is and skip to the next instance.
                        continue;
                    case PathCompleteBehaviour.Loop:
                        // Wrap front to back / back to front.
                        waypointIndex = (waypointIndex + waypoints.Length) % waypoints.Length;
                        break;
                    case PathCompleteBehaviour.Reverse:
                        // Bounce back to the point before last.
                        waypointIndex += (movementSpeeds[i] > 0f) ? -2 : 2;
                        // Reverse direction.
                        movementSpeeds[i] *= -1f;
                        break;
                    case PathCompleteBehaviour.PingPong: 
                        // Between two last waypoints.
                        waypointIndex = (waypointIndex) % waypointIndex + 1;
                        break;
                }
                nextWaypointIndices[i] = waypointIndex;
            }


            // Look up the waypoint we want to move toward next.
            Vector3 waypoint = waypoints[waypointIndex].transform.position;

            // Read this instance's speed,
            // to compute how far it should move in this frame.
            float travel = Mathf.Abs(movementSpeeds[i]) * Time.deltaTime;

            // Apply the motion.
            Vector3 direction = (waypoints[waypointIndex].transform.position - transform.position).normalized;
            Quaternion lookrotation = Quaternion.LookRotation(direction);
            transform.rotation = Quaternion.Slerp(transform.rotation, lookrotation, Time.deltaTime * 1);
            Vector3 position = instancesToMove[i].transform.position;
            position = Vector3.MoveTowards(position, waypoint, travel);
            instancesToMove[i].transform.position = position;

            // If we're within a configurable tolerance of the
            // destination waypoint, set our destination
            // to the next waypoint after it.
            if ((position - waypoint).sqrMagnitude < distanceFromWP)
            {
                nextWaypointIndices[i] += (movementSpeeds[i] > 0f) ? 1 : -1;
            }
        }
    }

    private void RandomSpeed()
    {
        for (int i = 0; i < instancesToMove.Length; i++)
        {
            if (randomSpeed && randoms == true)
            {
                movementSpeeds[i] = Random.Range(minRandomSpeed, maxRandomSpeed);
                randoms = false;
            }
            else
            {
                movementSpeeds[i] = constantSpeed;
            }
        }
    }
}

The waypoints screenshot:

Waypoints

The problem is that the Player is moving to the first door and can go through but in the next door he kind of stuck and moving backward to the first door then move between the two doors 2-3 times then the Player start rotating on place and everything get messed.

The idea is to make some kind of tour or like cutscene but instead animating the Player I thought using the doors as waypoints and maybe also the windows to show the view outside.

I created a small short video clip showing the problem.

The first part of the clip showing he player using the player controller and the mouse you can see when getting close to the door/s they are close and open many times fast.

The second part showing the waypoints and what happening to the player when getting to the second door(second waypoint).

Player movement with controller and then waypoints

This is the Player controller script:

using UnityEngine;
using System.Collections;

[RequireComponent (typeof (Rigidbody))]
[RequireComponent (typeof (BoxCollider))]

public class PlayerController : MonoBehaviour {

    private void Update()
    {
        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);
    }
}

And this is the Player MouseLook script:

using UnityEngine;
using System.Collections;

/// MouseLook rotates the transform based on the mouse delta.
/// Minimum and Maximum values can be used to constrain the possible rotation

/// To make an FPS style character:
/// - Create a capsule.
/// - Add the MouseLook script to the capsule.
///   -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
/// - Add FPSInputController script to the capsule
///   -> A CharacterMotor and a CharacterController component will be automatically added.

/// - Create a camera. Make the camera a child of the capsule. Reset it's transform.
/// - Add a MouseLook script to the camera.
///   -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour {

    public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
    public RotationAxes axes = RotationAxes.MouseXAndY;
    private float sensitivityX = 5f;
    private float sensitivityY = 5f;

    private float minimumX = 0f;
    private float maximumX = 360f;

    private float minimumY = -30f;
    private float maximumY = 45f;

    private float rotationY = 0f;

    void Update ()
    {
        if (axes == RotationAxes.MouseXAndY)
        {
            float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;

            rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
            rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);

            transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
        }
        else if (axes == RotationAxes.MouseX)
        {
            transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
        }
        else
        {
            rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
            rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);

            transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
        }
    }

    void Start ()
    {
        // Make the rigid body not change rotation
        if (GetComponent<Rigidbody>())
            GetComponent<Rigidbody>().freezeRotation = true;
    }
}

I can't figure out what is going on with the doors.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.