Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Trying to move character smoothly between 5 points, code not working

Discussion in 'Scripting' started by deen0_, Dec 29, 2022.

  1. deen0_

    deen0_

    Joined:
    Feb 10, 2021
    Posts:
    33
    Hey guys, hope you are doing well.

    I am trying to start get a jumping motion going for a character, and was looking for it to hit some critical points along the way.

    The first point being the origin, the second being the 'dip', the third being the max jump height, the fourth being the 'recoil', and the fifth being back to origin.

    My issue is, that the dip/recoil do not do anything for some reason.

    My transitions between the critical points seems to work fine, I see in the inspector the slerp finishing then the next one beginning, yet no downwards movement.

    This is mainly in my Jump() function within the code.

    I was wondering for any advice?

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class JumpBehavior : MonoBehaviour
    7. {
    8.     [Header("Movement Stats")]
    9.     [SerializeField] float jumpLength= 2f;
    10.     [SerializeField] float jumpHeight = 5f;
    11.     [Tooltip("Percentage")]
    12.     [SerializeField] float jumpRecoil = 0.15f;
    13.     [SerializeField] float jumpRecoilDepth;
    14.     [SerializeField] bool isJumping = false;
    15.     [SerializeField] float jumpSpeed = 2;
    16.     Vector3 initialPos; // To make sure jump ends where it starts
    17.     Vector3 jumpTrackPos; // To make sure each motion starts where last one ends
    18.     [SerializeField] Vector3[] criticalPoints;
    19.     [SerializeField] int jumpState = 0;
    20.     [SerializeField] float lerpPercent = 0f;
    21.     [SerializeField] Vector3 slerpTEMP;
    22.  
    23.     [SerializeField] Vector3 velocity;
    24.  
    25.     CharacterController characterController;
    26.     PlayerControls playerControls;
    27.  
    28.  
    29.     void Awake()
    30.     {
    31.         characterController = GetComponent<CharacterController>();
    32.         playerControls = new PlayerControls();
    33.         playerControls.Movement.Enable();
    34.  
    35.  
    36.         playerControls.Movement.Jump.performed += _ => isJumping = true;
    37.         playerControls.Movement.Jump.performed += _ => initialPos = transform.position;
    38.         playerControls.Movement.Jump.performed += _ => jumpTrackPos = initialPos;
    39.  
    40.         jumpRecoilDepth = jumpHeight * jumpRecoil;
    41.         criticalPoints = new Vector3[4];
    42.         criticalPoints[0] = new Vector3(0,-jumpRecoilDepth,0);
    43.         criticalPoints[1] = new Vector3(0, jumpHeight, 0);
    44.         criticalPoints[2] = new Vector3(0, -jumpRecoilDepth, 0);
    45.         criticalPoints[3] = Vector3.zero;
    46.  
    47.  
    48.     }
    49.  
    50.     private void Jump()
    51.     {
    52.         lerpPercent = Mathf.MoveTowards(lerpPercent, 1f, Time.deltaTime * jumpSpeed); // Tracks slerp progress
    53.  
    54.         Vector3 targetDir = jumpTrackPos + criticalPoints[jumpState];
    55.         slerpTEMP = Vector3.Slerp(transform.position, targetDir, lerpPercent);
    56.  
    57.         if (lerpPercent >= 1f && jumpState == 3) // Movement is done
    58.         {
    59.             jumpState = 0;
    60.             isJumping = false;
    61.             slerpTEMP = Vector3.zero;
    62.         }
    63.         else if (lerpPercent >= 1f) // Transition between critical points
    64.         {
    65.             jumpState += 1;
    66.             lerpPercent = 0f;
    67.             jumpTrackPos = transform.position;
    68.  
    69.         }
    70.     }
    71.     void Update()
    72.     {
    73.         if (isJumping) Jump();
    74.         characterController.Move(slerpTEMP*Time.deltaTime);
    75.     }
    76.  
    77.  
    78. }
    79.  
     
    Last edited: Dec 29, 2022
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,895
    This is the kind of things you should just do with an animation + root motion. There's no reason to code all this.

    In any case you can't set the
    transform.position
    of a game object being controlled by a CharacterController, as the latter will take precedence. You could guide your way through these jumps by calculating the direction of movement and using
    CharacterController.Move()
    , but again, this is animation territory.
     
  3. deen0_

    deen0_

    Joined:
    Feb 10, 2021
    Posts:
    33
    I was trying to attempt some procedural animation to an extent, I noticed mistake of both transform.translate and characterController, I have updated the code above.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,895
    And? Does it work?

    I'm going to assume not because
    CharacterController.Move
    expects a direction, not a position.

    And my point still stands. Use an animation. There's many tutorials on how to do this both directly in Unity or in software like Blender. And it'll need to be applied with Unity's mechanim system.
     
  5. frenchynyc

    frenchynyc

    Joined:
    May 14, 2015
    Posts:
    28
    It looks like the issue may be with the way you are calculating the targetDir variable in the Jump function.

    The criticalPoints array contains the offsets for each critical point relative to the starting position of the jump, but you are adding these offsets to the jumpTrackPos variable, which is the position of the last critical point. This means that the targetDir variable will always be the same as the jumpTrackPos variable, so the character will not move when you try to interpolate between these two points.

    To fix this, you can update the targetDir calculation to use the initialPos variable instead of the jumpTrackPos variable. This will make the targetDir variable the position of the next critical point relative to the starting position of the jump, and the character should move correctly as you interpolate between these points.

    Here's how you can modify the Jump function to do this:
    Code (CSharp):
    1. private void Jump()
    2. {
    3.     lerpPercent = Mathf.MoveTowards(lerpPercent, 1f, Time.deltaTime * jumpSpeed); // Tracks slerp progress
    4.  
    5.     Vector3 targetDir = initialPos + criticalPoints[jumpState];
    6.     slerpTEMP = Vector3.Slerp(transform.position, targetDir, lerpPercent);
    7.  
    8.     if (lerpPercent >= 1f && jumpState == 3) // Movement is done
    9.     {
    10.         jumpState = 0;
    11.         isJumping = false;
    12.         slerpTEMP = Vector3.zero;
    13.     }
    14.     else if (lerpPercent >= 1f) // Transition between critical points
    15.     {
    16.         jumpState += 1;
    17.         lerpPercent = 0f;
    18.         jumpTrackPos = transform.position;
    19.     }
    20. }
    21.  
    I hope this helps! Let me know if you have any other questions.