perhaps we can limit them by accessing the y (or z, I’m confused at this point which one is vertical) in-code, and setting it to zero when the translation occurs?
Y is always vertical. X => Left/Right, Y=>Up/Down, Z=>Forward/Back
Ideally, all animations should have no movement, allowing our states to handle the movement manually.
Rather than clearing the values, let’s remove the properties altogether…
this one introduced even more unwanted y-value movement…
I’m not sure what to do then. The animation you have is not compatible with what we are trying to do.
Here’s my suggestion at this point… go to Mixamo.com and find the Moving While Hanging animation.
Before downloading, check the “In Place” button. This should give you a clean animation with no motion changes.
You can also click Mirror to get a mirrored version that looks like it’s going the other way.
Then when you import it, since you’re using a Humanoid character, change the rig type to Humanoid in the importer.
lowkey scared to say that this is the exact animation I’ve been using the entire time (did the required changes, still no improvements)
OK we can probably let this go for now, and tomorrow try with the damage once more
Update: From what I just noticed… the values that change when we try moving on the ledge is on the Z-axis (from the debugger), for some reason… (although there’s still y-axis movement involved)
One last thing, if it helps in anyway, I’m still on Unity 2021 LTS
How about we set some y-axis boundaries for the ledge? As in, let the player automatically fall if he leaves the ledge, shouldn’t this solve the problem to some extent?
(I’m lowkey raging out of happiness right now behind the screen, and trying so so so hard not to scream here, but I just found out EXACTLY what was causing the issue, but now I stumbled into the natural successor):
Let’s start with the good news, here is the solution to this headache:
in ‘PlayerHangingState.Enter()’, the disabling, calculating, and then enabling controllers were literally responsible for the post-transformation of the y-axis of the player. This one hit me like a rock when I realized that the y-axis was being shifted POST animation (i.e: it happens when the player returns to the HANGING state, so I went to the hanging state and started messing with the enter a bit…). Anyway, these are the lines that I deleted to get it to work (I deleted the commented lines out):
Frankly speaking as well, I have absolutely no clue what the part I commented out did tbh either, but if it works and harms no one, then it works…
public override void Enter()
{
stateMachine.transform.rotation = Quaternion.LookRotation(ledgeForward, Vector3.up);
// Disabling the character controller, prior to hanging (similar to what we did when pulling our player up, when he detected a ledge)
// because the math won't work before deactivating the CharacterController:
// stateMachine.CharacterController.enabled = false;
// moving the player when hanging:
// stateMachine.transform.position = closestPoint - (stateMachine.LedgeDetector.transform.position - stateMachine.transform.position);
// Enabling the character controller again (we are done with the mathematical formula):
// stateMachine.CharacterController.enabled = true;
stateMachine.Animator.CrossFadeInFixedTime(HangingHash, CrossFadeDuration);
}
The bad news is, the natural successor bugs have shown up. How do we limit the player from going on after the ledge has ended? (If he hasn’t clicked the ‘S’ key, I want him to simply stay where he is and not transition to the movement while hanging state machine)… This bug still exists, and what if there is a corner, maybe a 90 degree house roof turn, for us to avoid? How do we just… turn, and latch on to that other Ledge? (if this one is too much, we can ignore it and just get him to fall instead). Down the line, after the major blend, I might integrate ‘Hanging Durability’, a variable that makes the player get tired of hanging if his Agility skill is too low for example… long-term future plan
To make it seem more natural though, can we use the movement that comes in the rig instead of the humanoid though? (I could’ve sworn I had this working at one point, maybe through a Generic Rig or something… not sure)
Again, before we proceed, thank you so so so much Brian for your script earlier, the re-make of my ‘PlayerMoveSidewaysWhileHanging.cs’ script. It was EXTREMELY helpful!
OK so here’s an update. To combat the fact that my player goes on to infinity with his ledge hanging, I gave this ‘forgotten’ challenge a go, and it worked in making him fall if the ledge is over (I would’ve wished that he’d stop when it ends, and wait for an ‘S’ key command for him to fall, but for now this should be fine). Here is how I solved it (and it works by the way):
in ‘LedgeDetector.cs’:
// when you no longer have a ledge to hold on to:
public event Action<Vector3, Vector3> OnFinishedLedge;
private void OnTriggerExit(Collider other) {
OnFinishedLedge?.Invoke(other.transform.forward, other.ClosestPointOnBounds(transform.position));
}
and then in ‘PlayerMoveSidewaysWhileHanging.cs’ (what a class name I got there… ):
// in 'Enter()':
stateMachine.LedgeDetector.OnFinishedLedge += NoLedgeDetected;
// in 'Exit()':
stateMachine.LedgeDetector.OnFinishedLedge -= NoLedgeDetected;
// New function (the function the Event is calling):
public void NoLedgeDetected(Vector3 ledgeForward, Vector3 closestPoint) {
stateMachine.SwitchState(new PlayerFallingState(stateMachine));
}
A little bit of experience with events, something I am, quite literally, terrible with… I’m slowly understanding their idea (just a bunch of functions subscribed to a keyword, that is fired from somewhere… so basically a bunch of function triggered at one point. In this case, they’re “Invoked” in 'LedgeDetector.OnTriggerExit()")
In programming we have a term called a “Corner Case”… this is where a formula works for all values but some value on the end.
A fantastic real world example of this is in exponents… any value raised to the 0th power is… always 1, so if you were writing a POW formula from scratch, the first thing you would check is to see if the exponent is zero, and if it is, simply return 1.
I only bring this up because in this sentence, you are quite literally asking for a corner case.
For now, that may be a bit complex.
Do you mean the animation motion? If you do, the ledge detection won’t work and your character will hang out for all the world to see regardless of what we do to fix a corner case or stop at the end of a ledge. We need the animation in place so the physics system can do it’s job. An animation that moves the rig without moving the capsule collider is a train wreck when you’re relying on physics to get the job done.
Well done, that’s the solution I was looking for.
If you wanted to force a stop, you could instead put a hard collider on the ends of the ledge and Character Controllwer will stop.
I think we crossed one when we were working on the 2-handed system, right? When my sword would wield for all conditions, but it was a nightmare to work with when the inventory was full… This was a corner case, right?
You did NOT just pull that on me
I’m not going for Rockstar-style details for now. I just want something exciting that people are willing to play, to be able to say someday “I made this (with the help of an amazing team )”
Fair enough, I got an extremely impressive result by all means, and I’m more than grateful for what we have accomplished so far, and what we are yet to accomplish xD
It’s these little moments that genuinely make me happy tbh, and make this whole train wreck of a project worth the fun. It might seem dumb, but it genuinely takes me a lot of effort to figure out some of these solutions
Umm… what’s a “hard collider”? Does it guarantee my character can turn around though? (I don’t want him purposely falling off a high building because an animation kept playing by accident tbh)
We actually had a stack of corner cases there… every one of those special handlings we did equipping sword or shield is a corner case. The normal default case (for everything else) is equip the item. For the sword and shield, you need to deal with inventory and unequipping possibly both a sword and shield and many combos in between.
It should take some effort. You don’t learn nearly as much when the solution is handed to you than you do when you craft the solution yourself. That’s why I’ve been doing more and more challenges. There’s nothing wrong with failure, in as much that we learn from our failures (and trust me, I’ve learned a LOT over 40+ years of coding, if you know what I mean).
Hard collider as in not a trigger. The physics system will report an overlap on a trigger. On a collider (non trigger), it will stop a CharacterController in it’s tracks, just as if it was on the groud.
Ladies and Gentlement… STACK OVERFLOW (It was the perfect chance for me to say it )
That’s why I honestly enjoy working with you. Not so hard, but definitely not so easy either. Thank you for being amazing by the way Brian
Speaking of which though, I still don’t understand which part of the following line:
// moving the player when hanging:
// stateMachine.transform.position = closestPoint - (stateMachine.LedgeDetector.transform.position - stateMachine.transform.position);
Was responsible for eliminating the y-axis value transformation tbh (Good naming from Nathan absolutely did help me figure this out significantly quicker, than I would’ve done otherwise)
Anyway, we can move on to the Combat issue, and hopefully once it’s done, I can start attempting to merge the projects together
Still a bit baffled on what’s going on here. I’ll read this a few times, eventually I’ll get it.
The ledge limit without falling is still important though, especially that in the future, with complex homes, jumping between roofs will be an important part of the parkour (if that’s something I’m throwing in)
Ultimately I was hoping to be able to parkour around a house similar to this one:
Trigger Collider. Your CharacterController can walk/fall right through this collider. The only thing that happens is that an OnTriggerEnter is called
Hard Collider (or just Collider), not a trigger. Your Character Controller can try to go through this, but the physics system will stop the Character Controller right in it’s tracks.
Just a little heads up to anyone working on a ledge advancement, down the road, turn off the trigger box on your ledge’s box collider. Why? Because if you hold your ledge sideways keys down the line and keep the trigger on, you’ll be able to hold on to your ledge way beyond the end of the ledge, introducing an unwanted bug of being able to ledge onto the air
TLDR: Turn off the ‘Is Trigger’ boolean box in your Box Collider
I just noticed that’s what we were talking about earlier… facepalm
BUT… If you’re somehow flying from a distance to hold onto the top of the ledge, the glitch comes back (The ‘Is Trigger’ solves it when you’re coming from beneath the trigger, but when coming from the top… it’s chaos again). This one:
My counter-solution would be to translate the player a little downwards so it acts like how it would otherwise… The problem is, Vectors don’t accept decimals, neither is Unity accepting floats as Vectors or allowing any dealing between them, so I’m still trying various alternatives (OR just put a rock so far away, but really how viable is this solution?)
TLDR: I want my player to translate -0.1 units downwards if he’s coming from a distance, so that the bug of hanging to a ledge beyond it’s horizontal length, if we are coming from jumping off a rock for example, goes away
The other issue would be to check if there’s a house roof on your way as you pull up (right now, my character can pull himself up into a house, and this is a glitch that nothing will ever be able to fix, except starting a new game). If there’s one, climb to the next trigger point over there (I just noticed we don’t have a “jump to next trigger point” state… this Parkour system will need some work, from my side at least, after we integrate this project into the RPG series)
Edit: I developed an entire parkour system from scratch, it’s miles ahead of this prototype, but with a few minor glitches… (but this one was a nightmare to make)