So far I have two separate issues:
-
Collisions to check if I’m on the wall layer stop working properly
-
Sprites won’t change depending on if I’m on the ground or wall layer.
Basically I have some simple bools to check if I’m colliding with the ground layer or the wall layer:
void OnCollisionStay(Collision collision){
if(collision.gameObject.layer == 8){
isOnGroundLayer = true;
}else{
isOnGroundLayer = false;
}
if(collision.gameObject.layer == 9){
isOnWallLayer = true;
}else{
isOnWallLayer = false;
}
}
void OnCollisionEnter(Collision collision){
isColliding = true;
}
void OnCollisionExit(Collision collision){
isOnGroundLayer = false;
isOnWallLayer = false;
isColliding = false;
}
I also have another check in my update function that checks if isColliding is false, and if so, set both isOnGroundLayer as well as isOnWallLayer to false. I noticed that the problem arises when I hit a wall while rotated 180 degrees. To do this I have an incredibly basic check for the A and D keys:
if(Input.GetAxisRaw("Horizontal") > 0){
transform.rotation = Quaternion.Euler(0, 180, 0);
}
if(Input.GetAxisRaw("Horizontal") < 0){
transform.rotation = Quaternion.Euler(0, 0, 0);
}
Which then rotates me accordingly. I checked the colliders and they work perfectly fine. But as soon as I hit a wall while rotated 180 degrees on the Y axis, my wall bool fails completely. Any ideas as to why this is happening?
For the second problem: I have another incredibly simple snippet that is supposed to change the sprite of my character when on a wall:
if(isOnWallLayer){
GetComponent<SpriteRenderer>().sprite = midairSprite;
}else{
GetComponent<SpriteRenderer>().sprite = defaultSprite;
}
In my start method, I set defaultSprite to the current sprite. I then have a public sprite that is for the wallClimbSprite, which is assigned fine. But it never switches the sprites, even when my wall jumping is working fine (when issue 1 hasn’t happened yet). I’ve looked at countless forums and answers but none have worked, nor have any of them been within the last 8 years which I suspect could be an issue, but I still haven’t found a recent one that works. Is the code just outdated or am I doing something wrong?
Entire Script (I know its way more complicated than it needs to be, but I’ll optimize it once I get can it working in the first place):
public class PlayerMovement : MonoBehaviour
{
public float movementSpeed;
public float jumpHeight;
public float velocityThreshold;
public float fallSpeed;
public float xWallForce;
public float yWallForce;
public float wallJumpTime;
public float fallDiff;
public Animator animator;
public Sprite wallClimbSprite;
public Sprite midairSprite;
Rigidbody rb;
SpriteRenderer sr;
Sprite defaultSprite;
bool isOnGroundLayer;
bool isOnWallLayer;
bool wallJumping;
bool isColliding;
void Start()
{
rb = GetComponent<Rigidbody>();
sr = GetComponent<SpriteRenderer>();
defaultSprite = GetComponent<SpriteRenderer>().sprite;
}
void Update()
{
if(animator.enabled == true){
sr.sprite = midairSprite;
}else{
sr.sprite = defaultSprite;
}
float hozInput = Input.GetAxisRaw("Horizontal");
if(isOnGroundLayer && !isOnWallLayer){
animator.SetFloat("Speed", Mathf.Abs(hozInput));
}
if(!isOnGroundLayer){
animator.SetFloat("Speed", 0);
}
if(isOnGroundLayer == false && isOnWallLayer == false){
animator.enabled = false;
}else{
animator.enabled = true;
}
if(isOnWallLayer){
sr.sprite = wallClimbSprite;
}else{
sr.sprite = defaultSprite;
}
GameObject[] walls = GameObject.FindGameObjectsWithTag("Wall");
GameObject nearestWall = FindNearest(walls, transform.position);
float curVelocity = Mathf.Abs(rb.velocity.x);
//jumping
if(Input.GetKeyDown(KeyCode.Space) && isOnGroundLayer){
rb.AddForce(Vector3.up * jumpHeight);
}
//wall jumping
if(Input.GetKeyDown(KeyCode.Space) && isOnWallLayer){
wallJumping = true;
Invoke("SetWallJumpingToFalse", wallJumpTime);
}
if(wallJumping){
float input = Input.GetAxisRaw("Horizontal");
rb.velocity = new Vector3(xWallForce * -input, yWallForce);
}
//movement
if(hozInput == 0){
rb.velocity = new Vector3(rb.velocity.x * 0.99f, rb.velocity.y, 0);
}
Vector3 force = new Vector3(hozInput * movementSpeed, 0, 0);
if(curVelocity <= velocityThreshold){
if(isOnWallLayer == false){
if(isOnGroundLayer){
rb.AddForce(force * movementSpeed * Time.deltaTime);
}else{
rb.AddForce((force * 0.5f) * movementSpeed * Time.deltaTime);
}
}
}
if(isOnWallLayer){
rb.AddForce(Vector3.up * fallSpeed * Time.deltaTime);
}
if(Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D)){
rb.velocity = new Vector3(rb.velocity.x / 2, rb.velocity.y, 0);
}
//gravity stuff
if(!isColliding){
rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y - fallDiff, 0);
}
//rotation
if(Input.GetAxisRaw("Horizontal") > 0){
transform.rotation = Quaternion.Euler(0, 180, 0);
}
if(Input.GetAxisRaw("Horizontal") < 0){
transform.rotation = Quaternion.Euler(0, 0, 0);
}
}
void OnCollisionStay(Collision collision){
if(collision.gameObject.layer == 8){
isOnGroundLayer = true;
}else{
isOnGroundLayer = false;
}
if(collision.gameObject.layer == 9){
isOnWallLayer = true;
}else{
isOnWallLayer = false;
}
}
void OnCollisionEnter(Collision collision){
isColliding = true;
}
void OnCollisionExit(Collision collision){
isOnGroundLayer = false;
isOnWallLayer = false;
isColliding = false;
}
void SetWallJumpingToFalse(){
wallJumping = false;
}
GameObject FindNearest(GameObject[] lookFor, Vector3 lookFrom){
GameObject closest = null;
float distance = Mathf.Infinity;
Vector3 position = lookFrom;
foreach (GameObject go in lookFor)
{
Vector3 diff = go.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance)
{
closest = go;
distance = curDistance;
}
}
return closest;
}
}