Search Unity

Vector3 ProjectOnPlane issue

Discussion in 'Scripting' started by nbg_yalta, Jun 7, 2019.

  1. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    To move CharacterController along slopes I'm using Vector3.ProjectOnPlane method to convert velocity vector, the problem is that converted vector is affected by slope angle, so it is always less than original, how can I fix it?
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class PlayerOnSlope : MonoBehaviour
    7. {
    8.  
    9.     public CharacterController controller;
    10.  
    11.     private Vector3 velocity;
    12.  
    13.     void Start()
    14.     {
    15.        
    16.     }
    17.  
    18.     void Update()
    19.     {
    20.         Vector3 input = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
    21.         velocity = SlopeAngle(input);
    22.  
    23.         controller.Move(velocity * Time.deltaTime);
    24.     }
    25.  
    26.     Vector3 SlopeAngle(Vector3 vector)
    27.     {
    28.         return Vector3.ProjectOnPlane(vector, Normal);
    29.     }
    30.  
    31.     private void OnGUI()
    32.     {
    33.         GUIStyle style = new GUIStyle();
    34.         style.fontSize = 30;
    35.         style.normal.textColor = Color.white;
    36.      
    37.         GUILayout.Label(velocity.magnitude.ToString(), style);
    38.     }
    39.  
    40.     Vector3 Normal
    41.     {
    42.         get
    43.         {
    44.             Ray ray = new Ray(transform.TransformPoint(controller.center), -Vector3.up);
    45.             RaycastHit hit = new RaycastHit();
    46.  
    47.             if (Physics.SphereCast(ray, controller.radius, out hit, Mathf.Infinity))
    48.             {
    49.                 return hit.normal;
    50.             }
    51.  
    52.             return Vector3.zero;
    53.         }
    54.     }
    55.  
    56.     private void OnDrawGizmos()
    57.     {
    58.         Gizmos.DrawLine(transform.position, transform.position + velocity);
    59.     }
    60. }
    61.  
    62.  
    ezgif-2-93015b3912ff.gif
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    so you want to maintain the velocity of the vector after projecting it onto a plane?

    Mind you, projecting onto a plane just gives you the amount of change in the direction of the surface of the plane, hence it being shorter (the shadow cast from a noon sun is shorter than the length of object casting the shadow)

    What you can do to get the full velocity back is normalize your new projected vector and multiply it by the magnitude of the original vector.

    Code (csharp):
    1.  
    2.     Vector3 SlopeAngle(Vector3 vector)
    3.     {
    4.         var v = Vector3.ProjectOnPlane(vector, Normal);
    5.         //NOTE - may want to check if v is a zero vector before normalizing, this will happen if Normal and vector are parallel
    6.         return v.normalized * vector.magnitude;
    7.     }
    8.  
    Also... 'SlopeAngle' is a terrible name for that method. That is so not what it's doing.
     
    SparrowGS and nbg_yalta like this.
  3. Suchoj

    Suchoj

    Joined:
    May 23, 2016
    Posts:
    1
    I think that you can use the idea of this post here and use the GetAngleDirection to determine when the slope is up or down, if you don't have this info.

    But what is needed to understand is that the projection is like a percentage of a vector over another. Then you can use this as a north to calculate the variation of velocity.
    If the slope is upward, then use
    Code (CSharp):
    1. velocity = input * (SlopeAngle(input).magnitude/input.magnitude);
    and if the slope is downward use
    Code (CSharp):
    1. velocity = input * (1 + (1 - SlopeAngle(input).magnitude/input.magnitude));
    SlopeAngle.png
     
    nbg_yalta likes this.
  4. CERPLEX

    CERPLEX

    Joined:
    Nov 11, 2021
    Posts:
    1
    So, my problem is a bit similar but. i was trying to establish a new vector3 and for some reason it would not highlight. i am afraid that this may make my code not work so I'm posting this while it's still under work.
    any help will be appreciated. he is my code:

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

    public class playermovement : MonoBehaviour
    {
    // Start is called before the first frame update
    void Start()
    {
    transform.position = new Vector3 (note the vector3 will not highlight here)
    }

    // Update is called once per frame
    void Update()
    {

    }
    }
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    Please just start your own threads rather than hijack another thread. Your post has nothing whatsoever to do with this thread from years ago. Also, please just use code-tags as the posts in the thread you're hijacking use.

    You want help on code that does absolutely nothing. I'm really not sure what to say about the code because it's a bare new script with a line of "transform.position = new Vector3" added.
     
    Lurking-Ninja and hippocoder like this.
  6. Additionally what @MelvMay said: finish your code and check the console if you have errors, fix them and then you can tell if you have problems with this piece of code. We can't help you with half-baked scripts.