There's a player and a slope in my scene. I want the player to automatically switch to 'climbing down' animation when he's at the top of the slope and moving down and similarly switch to 'climbing up' when he's at the bottom and moving up. I'm using the default 'character controller'. I've managed to get the slope angle with 'Vector3.Angle(transform.forward, hit.normal)' and the 'climbing up' is working fine since the angle is > 95 and that's the condition I stated. But when 'climbing down' the angle is not uniform and ranges from 30 - 140 and the condition I've stated is < 70 which is not satisfied all the time and hence the animation switches from 'climbing down' to 'climbing up' and vice versa. How do I get the right slope angle to differentiate between up slope and down slope?
Because the system you are using is at least partially successful, I'd suggest there are two options here:
The intermittent problem is due to the capsule collider on the Player Controller and (I assume) picking the first collision hit in the list. You could try grabbing all the hits into an array and loop over them to find the one with the lowest, or highest, Y value - then use this with your existing normal check. The nature of the collider's shape can throw up a number of hits, and their order is not always guaranteed.
The second option, and the one I used when I wanted to alter walk speed based on slope, is to fire a ray down from a fixed point in front of the character, and use the difference in height between the player transform's Y and the ray hit's Y to determine the slope. This is more accurate as you are sampling a single point.
The problem seems to be the inaccuracy observed on 'climbing down'. This can be fixed using a better sampling of raycast result while calculating the slope. One such method is to try a sphere cast with some extra raycast and using statistics (mean, median, mode). This method is very well illustrated in the following posts-