Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Move on path (Camera Relative Inputs)

Discussion in 'Scripting' started by xamur, Mar 29, 2020.

  1. xamur

    xamur

    Joined:
    Mar 27, 2014
    Posts:
    109
    Hello,

    I am currently working on a 3d platformer (using the character controller pro asset, just letting you know, ignore that) and I have two major problems that need to be fixed. I guess it would be better to create two different threads for each question, so if you can't help me with this one or even can help me with both, here is the other thread. Thank you!

    The functionality

    The player character got several scripts for different types of movements. Now I am working on a script that checks the world near the player for GameObjects with the tag "isClimable". If there is such a GameObject (e.g. a rope) and the player presses the "X" button, he will be moved to the GameObject and changes his movement style (that's where my problem starts).
    That means the core functionality of the script is: "attach" the player to a GameObject and move him along its mesh (both horizontally or vertically), after a key was pressed.

    The problem

    Because I couldn't figure out how to do it with the GameObject itself I used a free path system from the asset store: Bézier Path Creator, this can be modified at anytime. But I will consider to not use the asset in this case, maybe.
    I want that the player can move along the given path, but cannot move anywhere else, except if he jumps from the GameObject. I tried to do it as simple as it can be: if player presses W go up, S = go down., as an example. But then I noticed that this isn't good. I tried to impement the code where it depends on the camera view, where the player is going if I press WASD. That worked, but it was still possible for the player to move somewhere else and falling of the path, until he uses W or S again, then the player was teleportet back to the path. I hope you understood what I am trying to explain. There will be a gif aswell.

    The question
    What is the best way to implement the camera movement code part in my script, unfortunately I deleted the part where it worked for W and S. But as an example: the player is only allowed to move forward or backwards on a rope, he is not able to move left or right until he jumps of the rope and uses his normal movement again. But if the camera is on another angle left or right could also be seen as forward or backward. You know what I mean? :confused:

    example of two different movement directions
    GIF


    The script

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Lightbug.CharacterControllerPro.Core;
    5. using Lightbug.Utilities;
    6. using PathCreation;
    7.  
    8. namespace Lightbug.CharacterControllerPro.Implementation
    9. {
    10.  
    11. public class isClimbale : MonoBehaviour
    12. {
    13.     [SerializeField]
    14.     PathCreator pathCreator;
    15.  
    16.     [SerializeField]
    17.     EndOfPathInstruction endOfPathInstruction;
    18.  
    19.     [SerializeField]
    20.     float moveOnPathSpeed = 3;
    21.  
    22.     float pathDistanceTravelled;
    23.  
    24.    // [SerializeField]
    25.    // float moveToObjectSpeed = 10;
    26.  
    27.     float normalMovementSpeed;
    28.  
    29.     CharacterStateController characterStateController = null;
    30.     CharacterActor characterActor = null;
    31.     NormalMovement normalMovement = null;
    32.     Vector3 ClimableObjectPos;
    33.     Vector3 PlayerPos;
    34.     float Distance_;
    35.  
    36.     bool movePlayer = false;
    37.  
    38.  
    39.     void Awake ()
    40.     {
    41.       characterStateController = transform.root.GetComponent<CharacterStateController>();
    42.       characterActor = characterStateController.GetComponent<CharacterActor>();
    43.       normalMovement = characterStateController.GetComponent<NormalMovement>();
    44.     }
    45.  
    46.     // Update is called once per frame
    47.     void Update()
    48.     {
    49.       //acess to the speed of the normal movement sate script of the character controller
    50.       normalMovementSpeed = normalMovement.planarMovementParameters.speed;
    51.       //Debug.Log(Distance_);
    52.  
    53.       PlayerPos = GameObject.FindGameObjectWithTag("Player").transform.position;
    54.       ClimableObjectPos = GameObject.FindGameObjectWithTag("ClimableObject").transform.position;
    55.  
    56. //Distance between player and climable object
    57.       Distance_ = Vector3.Distance(PlayerPos, ClimableObjectPos);
    58.  
    59. //Checking distance
    60.       if(Distance_ < 5)
    61.       {
    62. //Debug.Log("Climable Object detected nearby!");
    63.         if (Input.GetKeyDown(KeyCode.X))
    64.         {
    65. //not sure if there is another way to do it, but because OnKeyDown is called only one time "MoveTowards" or something else wasn't working for me without using a bool
    66.           movePlayer = true;
    67.           //Debug.Log ("X Pressed");
    68.         }
    69.  
    70.         if (movePlayer == true)
    71.         {
    72. //I deleted the "MoveTowards" code because it wasn't working for now
    73.             if (Input.GetKey(KeyCode.W))
    74.             {
    75. //As far as I undertand: this is the complete path and how fast the player can move on it
    76.                 pathDistanceTravelled += normalMovementSpeed * Time.deltaTime / 2;
    77.                 transform.position = pathCreator.path.GetPointAtDistance(pathDistanceTravelled, endOfPathInstruction);
    78.                 //transform.rotation = pathCreator.path.GetRotationAtDistance(pathDistanceTravelled, endOfPathInstruction);
    79.             }
    80.  
    81.             if (Input.GetKey(KeyCode.S))
    82.             {
    83.                 pathDistanceTravelled -= normalMovementSpeed * Time.deltaTime / 2;
    84.                 transform.position = pathCreator.path.GetPointAtDistance(pathDistanceTravelled, endOfPathInstruction);
    85.                 //transform.rotation = pathCreator.path.GetRotationAtDistance(pathDistanceTravelled, endOfPathInstruction);
    86.             }
    87.  
    88.  
    89.         }
    90.       }
    91.       else
    92.       {
    93.         movePlayer = false;
    94.       }
    95.     }
    96.  
    97.   }
    98. }
    99.  
    My script isn't the best written. In some way it works, but not as good as I want it. It would be awesome if someone can help me fixing my problem(s) and may even improving the script. Stay healthy!
     
    Last edited: Mar 29, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,936
    One approach is to take the Vector3.Dot() of your motion and the tangent of the spline. You would use this result (a floating point value) to decide how much to move forward/backward.