Character align to surface normal ???

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

Not open for further replies.
1. 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

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.

3. Grune

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

Unknown identifier: 'hit'

:roll:

4. 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

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

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

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

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.

Joined:
Oct 22, 2008
Posts:
405

Joined:
Oct 22, 2008
Posts:
405
Any ideas?

11. 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

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
11.     public SphereCollider planet;           //collider for planet
12.
13.     void Start () {
14.         //consider scale applied to planet transform (assuming uniform, just pick one)
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();
34.         float headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
36.         //align with surface normal
37.         transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.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

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

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

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

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
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)
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();
35.       var headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
37.       //align with surface normal
38.       transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.rotation;
40.       transform.rotation = headingDelta * transform.rotation;
41.    }

17. 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

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?

19. 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

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

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

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

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.

Joined:
Dec 23, 2010
Posts:
214

25. 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

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

Oddly, I just posted this on the subject:

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

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

28. 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

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.
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.
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.
56.
57.       var headingDeltaAngle = Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed;
58.
60.
61.       //align with surface normal
62.
63.       transform.rotation = Quaternion.FromToRotation( transform.up, surfaceNormal) * transform.rotation;
64.
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

Joined:
Jun 11, 2013
Posts:
6
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

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.
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

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

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:

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);
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

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

Joined:
May 24, 2013
Posts:
10,805