My clamping when in a trigger of an object that has a default (0,0,0) rotation works as it should, but any object with any angle at all such as (0,45,0) will cause my camera to rotate forward based on my clamp degrees. I use a trigger like this to allow me to use as many of the same object as I want for my specific ‘wall running’ mechanic:
public void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Wall")) return;
canTurn = true;
wallObject = other.transform.parent;
}
void Update()
{
if (canTurn == true && Input.GetKeyDown(KeyCode.Z))
{
movement.enabled = false; // disable player movement script so it doesn't overlap with this script
if (currentRoutine != null) StopCoroutine(currentRoutine);
currentRoutine = StartCoroutine(Turn(wallObject));
}
if (isWallRunning)
{
// Do movements here
}
}
In my video, the first trigger that I enter has perfect clamping and I can only turn left or right a small amount. But when I step into the second trigger my camera instantly rotates forward based on my clamp value, and as a result the clamp doesn’t work properly because the camera had just rotated when it shouldn’t have.8s17hh
My entire camera code just incase, is here: https://pastebin.com/nh2zGwbA some of it is my own code and I found the general script on github, but everything else in it works perfectly.
I tried to fix this by resetting the rotation when entering the trigger using a vector positionForward = transform.forward and float Angle = Vector3.Angle(Vector3.forward, positionForward), then using ‘Angle’ inside my clamp to readjust the rotation of the player and wall, but that didn’t have any effect.
One trick I did for a complicated camera setup, was have an empty parent object, and child the camera to it. That way, the parent only needs to focus on a position, and possibly even a left/right modification. And the camera itself only needs to worry about a look up/down.
However it seems you may also be adding in a tilt/roll, which would further complicate the cameras rotation.
But the hard part is learning that if the camera tilts left(z90), if you now change the cameras left/right value(y90), it would now look up or down, because of it’s current rotation.
So having a hierarchy setup allows you to keep normal rotations, in a general sense. Which technically makes it more complex in one way, but much easier to understand in another. There are other ways of doing the same thing, like just adding a rotation.LookAt(), and just modifying it’s axis to rotate on as the perspective changes.
Now however, I already hear Kurt yelling “Cinemachine!”, so if you just want simple functionality I would look into that. But if you truly want to make your own camera setup, then brew up another pot of coffee, and get some aspirin on standby… Because you’ve now entered debug hell… lol
But personally I like to learn how it all works, and how I can modify things myself… So yes I have a lot of headaches.
But check this out: I got a new blurb I’m working on: how to make your own camera controller:
If you insist on making your own camera controller, the simplest way to do it is to think in terms of two Vector3 points in space: where the camera is LOCATED and where the camera is LOOKING.
Is Cinemachine not a lot more difficult and time consuming to set up? I’ve had it suggested a lot but all I can find are several third person videos and no first-person camera setups minus a brief official Unity tutorial
well… the thing you need to understand is, any function(or package), does all the same things as I mentioned by hard coding the values yourself. You put in one parameter or variable, and it simply returns the results you want.
So true, things can be much more simplified by using another’s already created method, but you’ll find that they lack in certain aspects that you might want to have in your methods. One trick I do is find the hard code on things, and find the meat and potatoes of what they do, and make my own function(which is time consuming and hard).
But I just like to understand how things tick, and how they operate so I understand it on a baser level. As I said, that’s just me…
I’ve never played with Cinemachine, so I can speak to it’s ease of use, or what it does great, or where it lacks.
And for LookAt(), you’ll have to dig into it more, and fully understand how it operates. Once you do, it takes out a lot of the leg work from doing it yourself(as does any pre-made function or package).
That’s the best part! or well for me it is, the debugging and learning how and why it works. I would also look into using Debug.DrawLine and it’s brother Debug.DrawRay. As I never would of grasped anything, without physically seeing what rotations and directions are actually doing.
I tested something overnight but it does nothing but cause a jittery effect until I exit trigger. Debugging shows me that it also still tries to rotate forward rather than towards my object… it makes no sense. I’ve used similar code elsewhere and it works. I just took that and expanded upon it:
I also edited my post to better show my trigger script code. I put this inside my trigger (which I have in my post above) that is in my other script. Basically what I do is, when I first enter the trigger of the wall, I need to press “Z”, which will then activate this coroutine through the canTurn bool. Once the coroutine ends, canTurn bool turns false, and isWallRunning turns true, which should allow for clamp. But the coroutine never ends.
That is the major problem, this happens all the time, and is a very common problem within these forums.
The thing you need to understand about coroutines, is they technically create their own script, and they run separately on their own each time they’re called. Which gives a compounding effect, and often will cause Unity to crash since so many of them can be running and called each frame.
So always make sure your coroutines are for something you want to be separate from your script, to run on their own, and that they only get called once.
I personally don’t use coroutines, nor do I think I ever will. If I need something to happen constantly within my script while the script is alive, it would simply be in my update method. And if I knew there’s a chance the script would disable, and need something to keep thinking after the fact, it would be handled in another script, whether existing or creating a new one(best example would be a separate death animation, if using object pooling).
And testing for run-away-coroutines is a little tricky, you’d need a frame counter, and have your print() debug mention it:
public class AlwaysExists
{
public static int frameCounter;
void Update()
{
frameCounter++;
}
}
// in problem area:
print($"value 1 now {value1} at frame {AlwaysExists.frameCounter}");
//print= value 1 now 37 at frame 136
//print= value 1 now 37 at frame 136
//print= value 1 now 37 at frame 136
Is it just preference that you don’t use coroutines or is it generally advised to try and move away from them? I’ve also heard this about while loops and even using LateUpdate().
But you can use them however you want, I’m just mentioning how they create problems, that are sometimes hard to debug.
Best way is to make sure it only runs once, so any call/invoke of a coroutine should be handled by a one-time bool, or something like it. That way it only gets called one time, and you’re sure it won’t be called multiple times.