Search Unity

Move player to nearest point of other gameobject after GetKeyDown

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 second problem starts, but ignore it for now).
    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.
    Now every time I press the "X" button the player gets moved to the starting point of the path and not the nearest point of the path next to the player. I don't know how to code it the best way so that it doesn't move the player to the start point rather to the nearest point. I hope you understood what I mean. If not, here is an example of what I am trying to do:

    vertically
    GIF

    or horizontally
    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,727
    One cheesy way to do it is iterate the bezier spline from start to finish, and get the position at each point, looking for which one is closest to the player, and that would tell you where in the curve to be.