Unity stop character controller jumping up mountains - unity3d

as most of you might know, the default character controller settings in unity allow you to simply jump up any mountain / hill, even if its more than the slope limit. Granted you can't WALK up it, but you can still jump up it while moving forwards.
In an attempt to fix this, I used the code from another answer:
void OnControllerColliderHit(ControllerColliderHit hit)
{
float radian = cont.slopeLimit * Mathf.Deg2Rad;
if (hit.normal.y <= radian)
{
canJump = false;
} else
{
canJump = true;
}
}
and in my update function I only jump if canJump is true (as you might have guessed)
So it almost works as expected, when the player approaches slopes that are beyond the slope limit (I THINK at least, if my radians calculation was correct, 'cause I don't really get what hit.normal.y is, if that's the same as the slope limit or not, so I kind of guessed... if anyone can correct me on that, that would help.)
Anyway, first of all I need to fix that fact that the character can't jump even when he's facing AWAY from the mountain, I don't know how to calculate if he's FACING the steep slope or not, only if he's colliding with it, so if anyone can help with that, that would be good, and (related):
I also can't figure out how to stop the player from jumping on these steep slopes from far away and staying on them, if he jumps on them or ends up on them however, he should simply slide down the mountain until he's on a regular slope, but I have no idea ow to get the CharacterContrller to slide down things, and especially not only until he reaches a regular slope?
Also it seems like this also applies (the fact taht he can't jump) to when the character is walking up stairs sometimes, but that's a big no-no 'cause he should always be able to jump up stairs if they're reasonably small enough, but I don't know how to differentiate between a terrain object and stairs...
If anyone can at least answer one of these three issues, that would be great (but prefereably all of them 'cause it's all part of the same question: How to just get normal character sliding / jumping regarding slpoes and stuff! (even though that wasn't the official title)

Related

Stuck Implementing A Way To Rotate A Rigidbody Towards A Point With Rigidbody.AddTorque

So I am kinda stuck on what to do now because as I said I am trying to use Rigidbody.AddTorque to rotate a rigid body towards a certain point, which I was going to use to align a player with a gravitational pull so they can be upright. I have got the input part of the code, I just don't have a way to rotate the player to align with it, without violating the laws of physics with Quaternion.FromToRotation and messing with my character controller too, which I am trying to make entirely physics based rotation wise too to avoid any other problems.
I have experimented with a couple of methods, first I tried adapting my character controller code which used Rigidbody.AddForce to move the player and also dampening unwanted movements, as Rigidbody.AddTorque is basically Rigidbody.AddForce but for rotations, however, it was too weak and just flopping around when I tried it, here's the code for the character controller for calculating the force needed for one axes:
if(projected_speed.x*speed == relative_v.x)
{
applied_speed.x = 0f;
}
else if(Mathf.Sign(projected_speed.x)== -1)
{
applied_speed.x = relative_v.x - Mathf.Abs(projected_speed.x*speed);
}
else if (Mathf.Sign(projected_speed.x) == 1)
{
applied_speed.x = projected_speed.x*speed - relative_v.x;
}
Where projected_speed is the speed the controller wants to be at,relative_v is the relative velocity, and applied_speed is the speed that will be actually applied in Rigidbody.AddForce.
Anyways so maybe I didn't use enough force, as the player is under a gravitational pull, but that would have probably made it flip out or something, anyways so the second thing I tried was a PID controller, and I managed to find a page which explains it pretty well, sadly don't have the link anymore, but when I tried this because you have to tune it, I was stuck doing it, and it just wasn't able to do anything and was just rolling around the floor and sometimes spinning, probably as it couldn't cope with gravity, so that didn't work, so does anyone know how I could finally do this and make my character able to right themselves according to gravity?
Sorry for not indicating that my issue is solved, click here for the answer, credit to Ruzihm.

Unity returning incorrect transform.rotation

In the endless running game I am creating, there is a mechanic called the jump pad. It basically takes in the change in the player's position since the last frame and converts that to an angle. Then it uses that along with the transform.rotation of the jump pad to figure out which direction to move the player in, as if it was actually bouncing off of it.
This algorithm would've been working perfectly except for one problem: Unity was reading an incorrect transform.rotation. When the jump pad was rotated 45 degrees, it read 21.92615 (after being multiplied with Mathf.Rad2Deg.) When the jump pad was rotated 20 degrees, it read 9.949307.
At first I thought it was being multiplied by an unknown constant for some reason, but after checking it through the Calculator app I found this to be not exactly the case. After a bit more experimenting I found that the possible "unknown constants", while close enough together, did seem to have a range from around 2 to around 2.1. And while I don't have the faintest clue how this is happening, it does seem to be remarkably consistent.
So my question is: what is this problem I am facing and is there any way I can fix it? Brief side note: I know this is not some other problem with the code because I stripped it down to the bare minimum:
public void OnTriggerEnter2D(Collider2D collision){
Debug.Log(collision.gameObject.transform.rotation.z * Mathf.Rad2Deg);
}
OK. After looking up the scripting API for transform.rotation and messing around a bit, I discovered that it was returning the z value of a quaternion and fixed it using the .ToEulerAngles() call.

Unity3D forcing object to a given orientation with minimum artificial effect

In my board game, the points are given by throwing 7 sea-shells cowry shell. These shells are dropped onto a sphere in Unity so they get rolled over randomly to different places. Once the rigidbody.isSleeping() returns true, I do a Raycast(from the belly side downwards) to figure out the orientation of the shell. If it is NOT a hit we know the shells belly is turned upside which means a point.
All is good and very realistic when in single player mode. Reason is I just activate the gravity of the shells and they dropped on to sphere, gets rolled randomly and when stopped i get the marks as stated above.
Now the problem is I am making the game multiplayer. In this case, I sent the randomly generated marks from the server and client will have to animate the shells to represent the marks. For example, if server send 3, out of 7 shells, 3 should have it's belly turned upside.
Trying to do this has been a major problem for me. I tried to transform.Rotate() when the velocity is reduced but it was not very reliable and sometimes acts crazy. Rotating afterrigidbody.isSleeping() works but very unrealistic.
I know I am trying to defy physics here, but there may be some ways to achieve what I want with minimum artificial effect.
I actually need some ideas.
Update - 1
After infor I receive below, I did found some information here, some advanced stuff here. Since the latter link had some advanced stuff, I wanted to start small. So I followed the first link and did below test.
I recorded the position, rotation & velocity of the sea shell with autosimulation enabled and logged them to a file. Then i used the Physics.Simulate() for the same scenario and logged the same.
Comparing the two tells me that data in both cases are kind of similar. So seems like for my requirements I need to simulate the sea-shell drop and then apply that sequence to the actual object.
Now my problem is how can I apply the results of physics.simulate() results (position, rotation, velocity etc..) to the actual sea-shell so the animation can be seen. If I set the positions to my gameobject within the simulation loop nothing happens.
public void Simulate()
{
rbdy = GetComponent<Rigidbody>();
rbdy.AddForce(new Vector3(0f, 0f, 10f));
rbdy.useGravity = true;
rbdy.mass = 1f;
//Simulate where it will be in 5 seconds
int i = 0;
while (simulateTime >= Time.fixedDeltaTime)
{
simulateTime -= Time.fixedDeltaTime;
Debug.Log($"position: {rbdy.position.ToString()} rotation: {rbdy.rotation.ToString()} Velocity {rbdy.velocity.magnitude}");
gameObject.transform.position = rbdy.position;
Physics.Simulate(Time.fixedDeltaTime);
}
}
So, how can I get this simulated data applied to actual gameobject in the scene?
Assume Physics are deterministic, just set the velocity and position and let it simulate on each client. Output should be the same. If the output differs slighly, you could adjust it and it may be only barely noticable.
Physics.simulate may be interesting to read, even if it's kind of the opposite of what you want.
You can throw in the client, record the steps in realtime or using physics.simulate (see point 2) and transmit the animation data as binary - then use it in the other clients to play the animation.

How to Troubleshoot Jitter in Unity - Vive VR

Update:
Shadows! It looks like the biggest problem I had was with shadows. I had absolutely every mesh giving and receiving shadows. Turning off shadows seems to reduce my issues by 99%. Not sure what the remaining 1% is, but this is way better! So on that note, my question still remains, how the heck could I have known it was shadows? Surely the graph below should have somehow told me this, yes?
Original Question:
The main question is how can I troubleshoot this further? I know there's a profiler thing but I'm not sure what to do with it. Is that what I want and need? Does this tell anyone anything? It should be representative of when the jitter is occurring.
More Background: I use a Vive controller to move by pulling the trigger. I perform a transform based on Time.DeltaTime using the vector position of the controller minus the y axis to know which way to move and how fast. There are tons of enemies and tons of spherical trees. The game seems to run quite well except when I look towards a particular direction. In trying to isolate what it is in that direction, I started turning stuff off such as enemies and the trees. Oddly enough, it makes it WORSE. The only way I can imagine this to be possible is if something is eating up resources all the more now that it's no longer fighting for them with other objects. But it would have to be doing it outside the regular frame loop or else the movement wouldn't appear impaired at all, right? That, or it's something wrong with how I move which now has more processing power to make it worse? I'm so at a loss. Anything wrong with this strategy?
public override void OnTriggerPulled(float triggerPullPercent)
{
if (!mainHand && triggerPullPercent > 0.05)
{
Vector3 goForward = transform.forward;
goForward.y = 0;
transform.parent.transform.Translate(goForward * triggerPullPercent * Time.deltaTime * 5f);
}
}
Even worse, the issue is inconsistent. After removing all the trees and seeing zero signs of improvement, I removed a single object just cuz it was ugly and not ready for the game anyway. Suddenly, things seemed quite a bit better than the "Worse" state it was in but it was more akin to the original jittery state which had me doing this to begin with. I added the object back in and oddly enough, it did not revert back to its worse state. So clearly it must not have been the object that made it any better/worse. I added my trees back in and it was suddenly back to the horrendous state. Now suspecting the trees, I removed them again and found no difference. Still crappy. So... not the trees or the object? I removed the one object and it was suddenly much better again. I can do this forever very repeatably. What gives? It's neither and both simultaneously? Any ideas? What more can I do to troubleshoot this? My current method is severely lacking.
Thanks!

Need Unity character controller to make sharp 90 degree turns and not slide when turning

I'm using the first person controller for my characters movement. On a left arrow keypress, I'd like the character to instantly rotate 90 degrees and keep moving forward. Currently, when I hit the arrow key, the character makes the sharp 90 degree turn, but the forward momentum the character previously had takes a second to wear off so the character ends up sliding in the direction he was previously moving a short bit.
The closest example I can think of to visually explain what I'm trying to do is how the character turns sharp in Temple Run. How my game is currently working, if I had the character on a ledge make a sharp left turn, he'd likely keep the original momentum and slide off the edge right after he turns.
Since my character is running on the x/z axis, I'm wondering if there would just be some way to maybe swap the directional velocity/momentum? The speed the character had on the x axis would instantly be switched to the z when it turns and the other would be set to zero. I'm obviously open to any solution that accomplishes what I'm looking for.
I dug into the CharacterMotor class in the first person controller, but have yet to find what part I can tweak to accomplish this.
I'd greatly appreciate any help.
Thank you.
You can try to stop the velocity of the Rigidbody before turning.
this.rigidbody.velocity = Vector3.zero;
this.rigidbody.angularVelocity = Vector3.zero;
If you want the object to continue like it did, you can try playing around with it by saving the current velocity in a variable, setting it to 0, rotate it and then putting back the old velocity (still forward).
If it works with global vectors (so from the point of view of the world, not the object), then you can try negativing the velocity, actually causing it to go 'backwards'. I can't test it for now but either way I think you need to set the velocity to zero first before turning the character.