Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Character align to surface normal ???

Discussion in 'Scripting' started by Grune, Nov 8, 2009.

Thread Status:
Not open for further replies.
  1. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    Hi i am at a Student Project, which could not be solved with standart unity gravity

    Character are suposed to move around a small planet.
    The Planet is not absolutely regular so it's not possible to solve this just by radius

    The only solution i could think about is to keep the characters aligned to the surface normal. Does anyone have an Idea how to do so?
     
  2. nickavv

    nickavv

    Joined:
    Aug 2, 2006
    Posts:
    1,801
    I do, actually. Let me grab it.

    Code (csharp):
    1. transform.rotation = Quaternion.FromToRotation (Vector3.up, hit.normal);
    Pretty sure that does it. Let me know if it works.
     
    guruprasadgv and Knightgum like this.
  3. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    it say's:

    Unknown identifier: 'hit'

    :roll:
     
  4. nickavv

    nickavv

    Joined:
    Aug 2, 2006
    Posts:
    1,801
    D'oh. I forgot the raycasting part. Here, try this instead:

    Code (csharp):
    1. var hit : RaycastHit;
    2. var castPos = Vector3(transform.position.x,transform.position.y-.25,transform.position.z);
    3. if (Physics.Raycast (castPos, -transform.up, hit)) {
    4.     transform.rotation = Quaternion.FromToRotation (Vector3.up, hit.normal);
    5. }
     
    Knightgum and Droidabi like this.
  5. Lab013

    Lab013

    Joined:
    Oct 22, 2008
    Posts:
    405
    I have tried that way, transform.up = hit.normal, and
    Code (csharp):
    1. var surfaceRot : Quaternion = Quaternion.FromToRotation (Vector3.up, hit.normal);    
    2.         var newRot : Quaternion = surfaceRot * Quaternion.AngleAxis(transform.rotation.eulerAngles.y, Vector3.up);
    3.         transform.rotation = Quaternion.Slerp(transform.rotation, newRot, 0.5);
    however none of them work as desired.
     
  6. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    Thanks a lot :)

    The cube are aligning semselves to the surface, one gets a jiggling. I gues it rotates and then the raycast gets a new position and it rotates again. I'm more into 3d- modeling, and now starting with javascript. My next step will be to figure out how to send the cube to the position of the raycast hit plus half the height of the Object.
     
  7. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    aha I did put the script in a function update > jiggling. In a fuction start the align and then stay calm. I gues it's more complicated with a character controler.
     
  8. immortius

    immortius

    Joined:
    Aug 7, 2009
    Posts:
    41
    With a Character Controller, you'ld probably want to make use of the OnControllerColliderHit() event rather than using raytracing, I imagine.
     
  9. Lab013

    Lab013

    Joined:
    Oct 22, 2008
    Posts:
    405
  10. Lab013

    Lab013

    Joined:
    Oct 22, 2008
    Posts:
    405
    Any ideas?
     
  11. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    to Lab013: I could not figure out your problem watching the video. Maybe you could post the spript and tell me your goal.
     
  12. Nick_Koufou

    Nick_Koufou

    Joined:
    Apr 26, 2008
    Posts:
    9
    I've been trying to work out a similar problem recently where I wanted to have an object orbit a planet like Mario Galaxy.

    After getting through quaternion hell (flipping at south pole) I eventually ended up with this:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class OrbitPlanet : MonoBehaviour {
    6.     public float rotationSpeed = 120.0f;
    7.     public float translationSpeed = 10.0f;  
    8.     public float height = 2.0f;             //height from ground level
    9.     private Transform centre;               //transform for planet
    10.     private float radius;                   //calculated radius from collider
    11.     public SphereCollider planet;           //collider for planet
    12.  
    13.     void Start () {
    14.         //consider scale applied to planet transform (assuming uniform, just pick one)
    15.         radius = planet.radius * planet.transform.localScale.y;
    16.         centre = planet.transform;
    17.         //starting position at north pole
    18.         transform.position = centre.position + new Vector3(0,radius+height,0);
    19.     }
    20.    
    21.     void Update () {
    22.         //translate based on input     
    23.         float inputMag  = Input.GetAxis("Vertical")*translationSpeed*Time.deltaTime;
    24.         transform.position += transform.forward * inputMag;
    25.         //snap position to radius + height (could also use raycasts)
    26.         Vector3 targetPosition = transform.position - centre.position;
    27.         float ratio = (radius + height) / targetPosition.magnitude;
    28.         targetPosition.Scale( new Vector3(ratio, ratio, ratio) );
    29.         transform.position = targetPosition + centre.position;
    30.         //calculate planet surface normal                      
    31.         Vector3 surfaceNormal = transform.position - centre.position;
    32.         surfaceNormal.Normalize();
    33.         //GameObject's heading
    34.         float headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
    35.         Quaternion headingDelta = Quaternion.AngleAxis(headingDeltaAngle, transform.up);
    36.         //align with surface normal
    37.         transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.rotation;
    38.         //apply heading rotation
    39.         transform.rotation = headingDelta * transform.rotation;
    40.     }
    41. }
    42.  
    All you have to do to try it out is:

    Create a sphere object and scale every axis up a bit (say by 10-15m)
    Create a cube and attach this script to it
    Script requires a sphere collider as an argument so select the sphere game object.
    Use arrow keys to fly around!

    Hope it helps
    Nick
     
    perevezentsev likes this.
  13. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    Thanks for the script NKoufou , thought i wont be able to learn much from it cause i'm just a little into javascript, but thanks. I tried it the way you described an it works pretty smoth. Does it work on iregular surfaces too ?

    My projekt at the moment looks like this:

    You are looking at the planet from the top down.
    You turn the planet and the cube slide acros to stay in the top middle, there's a point actracting them.

    I used the script from Podperson he posted in his topic: Faux Gravity making my brain spin
    And there's the problem: The Planet moves and the cubes (riggid bodies) slide. I did not figure out how riggid bodies could be transported on a moving Platform. They remain at their position and then fell down. They should stick to moving surface but move on their own when needed to.
     
  14. Nick_Koufou

    Nick_Koufou

    Joined:
    Apr 26, 2008
    Posts:
    9
    The section that updates the position can be changed to use a Collider.Raycast instead for irregular surfaces, this would return a contact point and a normal.

    I am not quite sure I understand what you are trying to do (you want the rigid body objects to stick to the surface when you rotate the planet?) but you might want to turn off gravity in the rigid body components to prevent them from sliding off.

    Nick
     
  15. Grune

    Grune

    Joined:
    Nov 8, 2009
    Posts:
    136
    Imagine a Platform which is sliding from one side of the room to another. ( like we knew from 1000 games )
    You walkaround and when you jump on the moving Platform you can walk on it AND get transported by it's movement.

    In Unity's Rigid bodies You jump on the platform and it slides away under your feet. Same with the moving Planet.
     
    perevezentsev likes this.
  16. cherub

    cherub

    Joined:
    Apr 26, 2006
    Posts:
    493
    I converted NKoufou's script to javascript for JS users.

    Im curious though, it was mentioned that this could be used for irregular survaces using raycast. how would that work?

    Code (csharp):
    1.  
    2. var rotationSpeed = 120.0;
    3. var translationSpeed = 10.0;
    4. var height = 2.0;          //height from ground level
    5. private var centre : Transform;            //transform for planet
    6. private var radius : float;               //calculated radius from collider
    7. var planet : SphereCollider ;         //collider for planet
    8.  
    9.  
    10. function Start ()
    11.  
    12. {
    13.       //consider scale applied to planet transform (assuming uniform, just pick one)
    14.       radius = planet.radius * planet.transform.localScale.y;
    15.       centre = planet.transform;
    16.       //starting position at north pole
    17.       transform.position = centre.position + Vector3(0,radius+height,0);
    18. }
    19.  
    20. function Update ()
    21.  
    22. {
    23.       //translate based on input      
    24.       var inputMag  = Input.GetAxis("Vertical")*translationSpeed*Time.deltaTime;
    25.       transform.position += transform.forward * inputMag;
    26.         //snap position to radius + height (could also use raycasts)
    27.       targetPosition = transform.position - centre.position;
    28.       var ratio = (radius + height) / targetPosition.magnitude;
    29.       targetPosition.Scale(Vector3(ratio, ratio, ratio) );
    30.       transform.position = targetPosition + centre.position;
    31.       //calculate planet surface normal                      
    32.       surfaceNormal = transform.position - centre.position;
    33.       surfaceNormal.Normalize();
    34.       //GameObject's heading
    35.       var headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
    36.       headingDelta = Quaternion.AngleAxis(headingDeltaAngle, transform.up);
    37.       //align with surface normal
    38.       transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.rotation;
    39.       //apply heading rotation
    40.       transform.rotation = headingDelta * transform.rotation;
    41.    }
     
  17. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    When you use a raycast, the RaycastHit object it returns contains a field for the normal of the surface at the point where the ray hit. You can use this to align the character (basically, just cast a ray downward to get the normal of the floor).
     
  18. jdams

    jdams

    Joined:
    Sep 13, 2010
    Posts:
    64
    I used NKoufou's code to create a simple box cruising around on a sphere but when I place objects on the sphere for it to run into I have some issues. I am using the JS code. When I apply rigid bodies to my obstacles they fly off into space, but if I apply it to the cube the collision works fine. However when the collision occurs my box bounces back and is stuck in this crazy spin. If I leave out the rigid bodies all together then my box just passes through the other meshes. Does anyone know how to stop the rotation or create collisions without the rigid bodies?

    Thanks for your help
     
  19. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    You shouldn't add rigidbodies to objects that are not supposed to move in the scene (like the obstacles). When you say the box goes into a crazy spin, how exactly is it spinning? It is possible to limit the rotation of a rigidbody object to one or two axes using a configurable joint component if that seems like it would fix the problem.
     
  20. jdams

    jdams

    Joined:
    Sep 13, 2010
    Posts:
    64
    Thanks for the reply Andeeee but I figured it out. It has something to do with the geometry of the cube. When the two flat faces collide it caused an odd rotation on the y axis. I decided instead to also apply a sphere collider to my cube on the "planet". Now the rotation is gone. I'm not really sure how this changed, but my only educated conclusion is the geometry of the colliders. Hmm... Guess I'll never know but it works!
     
  21. boomcrash

    boomcrash

    Joined:
    Aug 31, 2010
    Posts:
    72
    I'm using the C# code, and am having an issue the Player, AI controlled Enemies, and static objects ignoring collision. I'm using Capsules, Boxes, and Cylinders as collision bodies, but everything can pass through one another. Any suggestions?
     
  22. SteveZantes

    SteveZantes

    Joined:
    Nov 29, 2010
    Posts:
    13
    I don't know if this is the resolution to your problem... But i have use this script for push the player on the terrain:

    Code (csharp):
    1. TerrainGame.activeTerrain.SampleHeight(obj.transform.position)
    Where TerrainGame is a Terrain variable, so you need to assign your terrain game.
    This return exactly the height of the terrain of the player position. :)
     
  23. boomcrash

    boomcrash

    Joined:
    Aug 31, 2010
    Posts:
    72
    Should this line be applied to the characters or to the terrain itself? Should this be used to replace the other script?

    The main script posted on this thread works really well to simulate faux gravity, but I'm not sure why the characters are ignoring collision, when the same prefabs work in a normal level.
     
  24. cemC

    cemC

    Joined:
    Dec 23, 2010
    Posts:
    214
    Thanks for answers
     
  25. lusho_games

    lusho_games

    Joined:
    Jun 4, 2011
    Posts:
    63
    this script is great, how can you use it for bullets or rockets objects to follow the curvature of the planet ?
    I know that if you add the script currently as it is to the bullets they will follow the curvature but only if you move it yourself with the horizontal / vertical axis. I tried disabling that part of the code but it didn't work right. Any help will be appreciated.
    here it is a link to live preview what I'm working on:

    http://www.amazonarecords.com.ve/metraplayers/terminalSphere/WebPlayer/WebPlayer.html

    as you can see, if you shoot bullets go on a straight line.

    thanks
     
  26. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    You will need to fake gravity for bullets.

    Oddly, I just posted this on the subject:
    http://forum.unity3d.com/threads/102466-Planar-movement-on-spherical-surface

    Code (csharp):
    1.  
    2. var currentY=0.0;
    3. var bulletDampen = 0.1;
    4.  
    5. function Start(){
    6. var planet=GameObject.Find("Planet").transform;
    7. currentY=(transform.position - planet.position).magnitude;
    8. }
    9.  
    10. function Update(){
    11. var planet=GameObject.Find("Planet").transform;
    12. var bullet=transform;
    13.  
    14. bullet.position=upVector * currentY;
    15. var upVector=(bullet.position - planet.position).normalized;
    16. var lookAtVector=((bullet.position + rigidbody.velocity.normalized) - planet.position).normalized;
    17.  
    18. bullet.LookAt(lookAtVector * currentY, upVector);
    19. rigidbody.veloctiy = bullet.forward * rigidbody.velocity.magnitude;
    20. currentY * = 1 - bulletDampen * Time.deltaTime;
    21. }
    22.  
    What this does is to maintain bullet distance from the planet core, maintain's bullet velocity for the duration of the bullet and forces bullet drop over the curvature.

    What it does not do is to allow arcing. To do this, you would need to add bullet climb to counteract the bullet drop.
     
  27. emannazir

    emannazir

    Joined:
    Jan 28, 2012
    Posts:
    138
    hey can any one provide me the script for cube?
     
  28. emannazir

    emannazir

    Joined:
    Jan 28, 2012
    Posts:
    138
    can you provide me the source code files in through drop box?
     
  29. D_e_l_t_a

    D_e_l_t_a

    Joined:
    Jan 2, 2009
    Posts:
    72
    Hi,

    I'm using the JS code provided by cherub earlier in this thread;

    Code (csharp):
    1. var rotationSpeed = 120.0;
    2.  
    3. var translationSpeed = 10.0;
    4.  
    5. var height = 2.0;          //height from ground level
    6.  
    7. private var centre : Transform;            //transform for planet
    8.  
    9. private var radius : float;               //calculated radius from collider
    10.  
    11. var planet : SphereCollider ;         //collider for planet
    12.  
    13. function Start ()
    14.  
    15. {
    16.  
    17.       //consider scale applied to planet transform (assuming uniform, just pick one)
    18.  
    19.       radius = planet.radius * planet.transform.localScale.y;
    20.  
    21.       centre = planet.transform;
    22.  
    23.       //starting position at north pole
    24.  
    25.       transform.position = centre.position + Vector3(0,radius+height,0);
    26.  
    27. }
    28.  
    29. function Update ()
    30.  
    31. {
    32.  
    33.       //translate based on input      
    34.  
    35.       var inputMag  = Input.GetAxis("Vertical")*translationSpeed*Time.deltaTime;
    36.  
    37.       transform.position += transform.forward * inputMag;
    38.  
    39.         //snap position to radius + height (could also use raycasts)
    40.  
    41.       targetPosition = transform.position - centre.position;
    42.  
    43.       var ratio = (radius + height) / targetPosition.magnitude;
    44.  
    45.       targetPosition.Scale(Vector3(ratio, ratio, ratio) );
    46.  
    47.       transform.position = targetPosition + centre.position;
    48.  
    49.       //calculate planet surface normal                      
    50.  
    51.       surfaceNormal = transform.position - centre.position;
    52.  
    53.       surfaceNormal.Normalize();
    54.  
    55.       //GameObject's heading
    56.  
    57.       var headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
    58.  
    59.       headingDelta = Quaternion.AngleAxis(headingDeltaAngle, transform.up);
    60.  
    61.       //align with surface normal
    62.  
    63.       transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.rotation;
    64.  
    65.       //apply heading rotation
    66.  
    67.       transform.rotation = headingDelta * transform.rotation;
    68.  
    69.    }
    I have it working to great effect but now I'm trying to modify the code to act more Asteroids-like, with wild (though variable) inertia. I can mange inertia easily enough on a flat plane but I can't get this script to move my object around a sphere AND accelerate with a ton of inertia. I've been trying to add a Rigidbody with some force behind it but it messes up and breaks the spherical movement.
    Anyone with a line of code and a quick rundown of what's involved to expand this script a little further ?
     
  30. malikcgcs

    malikcgcs

    Joined:
    Jun 11, 2013
    Posts:
    9
    how i can make ( not regular planet) have gravity and it snap all object to its surface

    and i can walk on it

    :(
     
  31. sdgd

    sdgd

    Joined:
    Jan 15, 2013
    Posts:
    81
    I've just made a robust code for it will still work on it in future but you propably won't see the code, ... untill now I've got: jump, gravity, move around planet.

    was struggling with it for more than a week, ... was wanting to use collider but dint't go well through as on collision works only 1 time while here can be made with every move witch is much better otherwise I could do it with normal collider witch I'd prefer as of physics of guns, ...

    all you need is:
    GameObject with: Character controller (prefered sphere height), Movement script
    child GameObject with: Graphics, MouseLookX script
    child GameObject with: Camera, MouseLookY script

    Scripts:
    Mouse Look X
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MouseLookX : MonoBehaviour {
    6.     public float MouseSensitivityX = 1;
    7.     void Update (){
    8.         transform.localEulerAngles += new Vector3(  0, Input.GetAxis("Mouse X") * MouseSensitivityX, 0);
    9.     }
    10. }
    11.  
    Mouse Look Y

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MouseLookY : MonoBehaviour {
    6.     public float MouseSensitivityY = 1;
    7.     void Update(){
    8.         transform.localEulerAngles += new Vector3 (Input.GetAxis("Mouse Y") * MouseSensitivityY, 0, 0);
    9.     }
    10. }
    11.  
    Some added Math functions:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public struct MathFunctions {
    6.     // always positive
    7.     public float Positive (float FloatToChange){
    8.         if (FloatToChange < 0){
    9.             return (FloatToChange * (-1) );
    10.         }
    11.         return FloatToChange;
    12.     }
    13.     // Distance
    14.     public float Distance (Vector3 From, Vector3 To){
    15.         float TempX;
    16.         float TempY;
    17.         float TempZ;
    18.         TempX = From.x - To.x; TempX *= TempX;
    19.         TempY = From.y - To.y; TempY *= TempY;
    20.         TempZ = From.z - To.z; TempZ *= TempZ;
    21.         return Mathf.Sqrt(TempX + TempY + TempZ);
    22.     }
    23.     public Vector3 DirectionDistancePoint (Vector3 From, Vector3 To, float Length){
    24.         return (From + (To.normalized * Length) );
    25.     }
    26.     // Distance / sec
    27.     public float Vector3SpeedPerSec (Vector3 From, Vector3 To, float InTime){
    28.         return Positive( (Distance(From, To) ) / InTime  );
    29.     }
    30.     public Vector3 Direction (Vector3 From, Vector3 To){
    31.         return (To - From).normalized;
    32.     }
    33. }
    34.  
    35.  
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Movement : MonoBehaviour {
    6.     MathFunctions MF;
    7.    
    8.     public float Speed = 10;
    9.     public Transform Planet;
    10.     public Transform LocalOrientation;
    11.    
    12.     private GroundDetection GDet;
    13.    
    14.     // I need to learn how to implement it
    15.     public AnimationCurve slopeSpeedMultiplier = new AnimationCurve (new Keyframe(-90, 1), new Keyframe(0, 1), new Keyframe(90, 0));
    16.    
    17.     // character controller from now on
    18.     CharacterController Controller;
    19.     public Transform Platform;
    20.    
    21.    
    22.     public float PlanetDistance;
    23.     public float LastPlanetDistance;
    24.     Vector3 LookAtPlanet = Vector3.zero;
    25.    
    26.     // Done something in the work
    27.     public float LastHitTime = 0;
    28. //  public float Distance = 0;
    29.     public bool Grounded = false;
    30.     public Vector3 LastSlopeTestPosition = Vector3.zero;
    31.     public Vector3 LastGroundTestPosition;
    32. //  public Vector3 Velocity = Vector3.zero;
    33.     public Vector3 MovementVelocity = Vector3.zero;
    34.     public float MovingStartTime = 0;
    35.     public float MovingStartStopTime = 0;
    36.     public float MovingTime = 0;
    37. //  public float MovingToStopTime = 0;
    38.     public Vector3 TempInputVelocity = Vector3.zero;
    39.     public Vector3 JumpVelocity = Vector3.zero;
    40.     public Vector3 GravityVelocity = Vector3.zero;
    41.     public Vector3 Gravity = Vector3.zero;
    42.     public float GravityStrength = 20;
    43.     public float JumpStartDistance = 0;
    44.     public bool StillJumping = false;
    45.     public bool StillInMovement = false;
    46.     public bool StoppingMovement = false;
    47.     public float JumpStrength = 10;
    48.     public float MovementSpeed = 1;
    49.     public float AccelerationTime = 1;
    50.     public float JumpHeight = 20;
    51.    
    52.     public bool AccelerationMovement = false;
    53.    
    54.     void Start(){
    55.         Controller = GetComponent("CharacterController") as CharacterController;
    56.         // so we don't end up teleporting at x0y0z0 if something unexpected happenes
    57.         LastSlopeTestPosition = transform.position;
    58.     }
    59.    
    60.  
    61.     // why fixed update? had something in my mind that I need it forgot it why, ... seems to be working well with normal update too less calculations to be made with it
    62.     // if I'm wrong something might not be sinhronized, ... don't know, ...
    63.     void Update() {
    64.         // Align to planet
    65.         // only south pole doesn't seem to be working
    66.         transform.rotation = Quaternion.FromToRotation (Vector3.up, -(Planet.position - transform.position) );
    67.         LookAtPlanet = -transform.up;
    68.        
    69.         if (Grounded){
    70.             // 1/2 Grounded false if not colliding
    71.             IsStillGrounded();
    72.         }
    73.         // we check if we are still grounded.
    74.         if (Grounded){
    75.             InputMoveMotion();
    76.             // inside 2/2 Grounded false if press a key
    77.             InputJumpMotion();
    78.         }
    79.         // if we jump we are still not using gravity
    80.         else if (! StillJumping){
    81.             GravityMotion();
    82.         }
    83.         if (StillJumping){
    84.             ContinueJumpMotion();
    85.         }
    86.         MoveChar();
    87.     }
    88.     void IsStillGrounded (){
    89.         // we are not moving OR we are in air
    90.         if (LastHitTime < (Time.time - Time.deltaTime * 2) ){
    91.             // we are moving in mid air
    92.             if (LastGroundTestPosition != transform.position){
    93.                 Grounded = false;
    94.             }
    95.           //else {we aren't in motion}
    96.         }
    97.         LastGroundTestPosition = transform.position;
    98.     }
    99.    
    100.     public void InputMoveMotion(){
    101.         Vector3 ImputVelocity = Vector3.zero;
    102. //      if (/*AI*/){
    103. //          ImputVelocity +=    /*all the moves*/
    104. //          ImputVelovity.Normalize();
    105. //      }
    106. //      else {
    107.             if (Input.GetKey(KeyCode.UpArrow)){
    108.                 ImputVelocity += ( LocalOrientation.transform.forward);
    109.             }
    110.             if (Input.GetKey(KeyCode.DownArrow)){
    111.                 ImputVelocity += ( -LocalOrientation.transform.forward);
    112.             }
    113.            
    114.             if (Input.GetKey(KeyCode.LeftArrow)){
    115.                 ImputVelocity += ( -LocalOrientation.transform.right);
    116.             }
    117.             if (Input.GetKey(KeyCode.RightArrow)){
    118.                 ImputVelocity += ( LocalOrientation.transform.right);
    119.             }
    120.             // direction length to 1 unit
    121.             ContinueMoveMotion(ImputVelocity.normalized);
    122. //      }
    123.     }
    124.     void ContinueMoveMotion(Vector3 InputVelocity){
    125.         if (! AccelerationMovement){
    126.             MovementVelocity = InputVelocity;
    127.             return ;
    128.         }
    129.        
    130.        
    131.         // seems to be working more tests need to be done, ...
    132.        
    133.         if (InputVelocity != Vector3.zero){
    134.             TempInputVelocity = InputVelocity;
    135.             // we didn't ended the stop
    136.             if (StoppingMovement){
    137.                 StoppingMovement = false;
    138.                 MovingStartTime = Time.time - MovingTime;
    139.             }
    140.             // we are just starting to move
    141.             else if (LastGroundTestPosition == transform.position  ! StillInMovement){
    142.                 MovingStartTime = Time.time;
    143.             }
    144.             StillInMovement = true;
    145.             if (AccelerationTime > (Time.time - MovingStartTime)){
    146.                 MovingTime = (Time.time - MovingStartTime);
    147.             }
    148.             else {
    149.                 MovingTime = AccelerationTime;
    150.             }
    151.             // where we will move
    152.             MovementVelocity = InputVelocity * MovingTime;
    153.         }
    154.         else {
    155.             if (StillInMovement  ! StoppingMovement){
    156.                 StoppingMovement = true;
    157.                 MovingStartStopTime = Time.time + MovingTime;
    158.             }
    159.             // I don't need this but so it doesn't calculate all the time but just veryfy the bool
    160.             if (StoppingMovement){
    161.                 MovingTime = MovingStartStopTime - Time.time;
    162.             }
    163.             // if we are inside stopping time
    164.             if (MovingTime >= 0){
    165.                 MovementVelocity = TempInputVelocity * MovingTime;
    166.             }
    167.             // if we stopped totally
    168.             else {
    169.                 MovementVelocity = Vector3.zero;
    170.                 StillInMovement = false;
    171.                 StoppingMovement = false;
    172.             }
    173.         }
    174.        
    175.     }
    176.     void InputJumpMotion(){
    177.         // 2/2 if we jump we know we aren't grounded
    178.         if (Input.GetMouseButton(2)){
    179.             JumpVelocity = transform.up * JumpStrength;
    180.             Grounded = false;
    181.             StillJumping = true;
    182.         }
    183.         JumpStartDistance = MF.Distance(transform.position, Planet.position);
    184.     }
    185.     void ContinueJumpMotion(){
    186.         PlanetDistance = MF.Distance(transform.position, Planet.position);
    187.         // if we stop pressing jump we stop getting in air
    188.         if (Input.GetMouseButtonUp(2)){
    189.             StillJumping = false;
    190.             JumpVelocity = Vector3.zero;
    191.         }
    192.         // if we reached our jump height we stop getting more in height
    193.         else if (JumpStartDistance + JumpHeight < PlanetDistance){
    194.             StillJumping = false;
    195.             JumpVelocity = Vector3.zero;
    196.         }
    197.         else if (StillJumping){
    198.             JumpVelocity -= (-transform.up * 0.3f * Time.deltaTime);
    199.         }
    200.     }
    201.     void GravityMotion (){
    202.         GravityVelocity = MF.Direction(transform.position, Planet.position).normalized * GravityStrength;
    203.     }
    204.     void MoveChar(){
    205.         if (StillJumping){
    206.             GravityVelocity = Vector3.zero;
    207.         }
    208.         if (Grounded){
    209.             Controller.Move( (MovementVelocity * MovementSpeed) * Time.deltaTime);
    210.         }
    211.         else {
    212.             Controller.Move(  ( (MovementVelocity * MovementSpeed) + JumpVelocity + GravityVelocity) * Time.deltaTime);
    213.         }
    214.     }
    215.     void OnControllerColliderHit (ControllerColliderHit hit){
    216.         // the only indicator we are grounded
    217.         // if it's less than 45° we are grounded
    218.         float CurrentSlope = (Vector3.Angle(LookAtPlanet, hit.normal) -180 )*-1;
    219.         if (Controller.slopeLimit > CurrentSlope){
    220.             Grounded = true;
    221.             LastHitTime = Time.time;
    222.             LastSlopeTestPosition = transform.position;
    223.         }
    224.         // if we are still grounded means we are on 45° + slope
    225.         else if (Grounded  Controller.slopeLimit < CurrentSlope){
    226.             // we need to teleport back to slope below 45°
    227.             transform.position = LastSlopeTestPosition;
    228.         }
    229.        
    230.         /****** START DEBUG Hit COMPONENTS ******
    231.         // world point
    232. //      Debug.Log("Point: " + hit.point);
    233.         // oposite of direction
    234. //      Debug.Log("Normal: " + hit.normal); // World Direction
    235.         // direction witch was forced back
    236. //      Debug.Log("MoveDirection: " + hit.moveDirection); // Local Direction  something strange unexplained about it
    237.         // more length that's stopped bigger number it'll return
    238. //      Debug.Log("moveLength: " + hit.moveLength);
    239. //      Platform = hit.transform;
    240.         /****** END DEBUG Hit COMPONENTS ******/
    241.     }
    242. }
    243.  
     
  32. Colamaeleon

    Colamaeleon

    Joined:
    Mar 9, 2015
    Posts:
    1
    I know I'm a bit late. But doing this is acually fairly easy:

    Code (CSharp):
    1. Ray ray = new Ray(transform.position, -transform.up);
    2. RaycastHit hit;
    3. Physics.Raycast(ray,out hit);
    4. if(hit.normal != Vector3.zero){
    5.   transform.up = hit.normal;
    6. }
     
    stor314 likes this.
  33. wantnon

    wantnon

    Joined:
    Mar 31, 2015
    Posts:
    2
    i meet the same question, and solved it with success. the trick is recalculate "forward" using new "up" and then call Quaternion.LookRotation to get the correct rotation.
    the result as blew:
    QQ20150331-1.png QQ20150331-2.png

    the code:
    Code (CSharp):
    1. //note, the code here suppose our character use a capsuleCollider and the floors' layerMask is "floor"..
    2.  
    3.      //..if yours' is not, you should make some change.
    4.  
    5.  
    6.         RaycastHit hitInfo;
    7.         Vector3 capsuleColliderCenterInWorldSpace=GetComponent<CapsuleCollider> ().transform.TransformPoint (GetComponent<CapsuleCollider>().center);
    8.         bool isHit=Physics.Raycast (capsuleColliderCenterInWorldSpace,new Vector3(0f,-1f,0f),out hitInfo,100f,LayerMask.GetMask("floor"));
    9.  
    10.         Vector3 forward=GetComponent<Rigidbody>().transform.forward;
    11.      
    12.         Vector3 newUp;
    13.         if (isHit) {
    14.             newUp = hitInfo.normal;
    15.         } else {
    16.             newUp = Vector3.up;
    17.         }
    18.         Vector3 left = Vector3.Cross (forward,newUp);//note: unity use left-hand system, and Vector3.Cross obey left-hand rule.
    19.         Vector3 newForward = Vector3.Cross (newUp,left);
    20.         Quaternion oldRotation=GetComponent<Rigidbody>().transform.rotation;
    21.         Quaternion newRotation = Quaternion.LookRotation (newForward, newUp);
    22.  
    23.      float kSoftness=0.1f;//if do not want softness, change the value to 1.0f
    24.         GetComponent<Rigidbody> ().MoveRotation (Quaternion.Lerp(oldRotation,newRotation,kSoftness));
     
  34. Nevleon06

    Nevleon06

    Joined:
    Jun 6, 2021
    Posts:
    3
    How could I get the angle of the normal im hitting? so i know like the slope angle
     
  35. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,315
    Please create your own post to ask a question, don't necro a thread from 2015.
     
Thread Status:
Not open for further replies.