2.5D sidescrolling platformer character controller problems
Asked Answered
D

2

0

I’m thinking about remaking a character controller that has been causing nothing but problems. The main problem is that it sticks to walls whenever you hold down the move because of addforce based movement. The jumping mechanic also has a problem where if the character is right next to a wall, the jump is less effective. I’ve tried fixing it using 3D physics materials, which had no effect, so either I should change something in the script or rewrite the script entirely. The plan for the future is to have the character follow a spline path, so if there is anything I should plan for, please let me know.

UPDATE:
I fixed the wall sticking issue by adding a frictionless physics material to the character as well as the wall.

    using UnityEngine;
    using System.Collections;
    
    // Require these components when using this script
    [RequireComponent(typeof (Animator))]
    [RequireComponent(typeof (CapsuleCollider))]
    [RequireComponent(typeof (Rigidbody))]
    public class Character_Controller : MonoBehaviour {
    
    
    	//[HideInInspector]
    	public bool facingRight = true;			// For determining which way the player is currently facing.
    	//[HideInInspector]
    	public bool jump = false;				// Condition for whether the player should jump.
    	public bool inSac = false;
    	public LayerMask layerMask;
    	public float moveForce = 365f;			// Amount of force added to move the player left and right.
    	public float maxSpeed = 5f;				// The fastest the player can travel in the x axis.
    	//public AudioClip[] jumpClips;			// Array of clips for when the player jumps.
    	public float jumpForce = 1000f;			// Amount of force added when the player jumps.
    	//public AudioClip[] taunts;				// Array of clips for when the player taunts.
    	//public float tauntProbability = 50f;	// Chance of a taunt happening.
    	//public float tauntDelay = 1f;			// Delay for when the taunt should happen.
    	//public int layerMask = 1 << LayerMask.NameToLayer ("Ground");
    	
    	//private int tauntIndex;					// The index of the taunts array indicating the most recent taunt.
    	//private Transform groundCheck;			// A position marking where to check if the player is grounded.
    	private Vector3 vOffset;
    	private bool grounded = false;			// Whether or not the player is grounded.
    	private bool walled = false;			//Whether or not the player is against a wall
    	//private bool walledRight = false;
    	private Animator anim;					// Reference to the player's animator component.
    	private CapsuleCollider col;
    	
    	void Awake()
    	{
    		// Setting up references.
    		//groundCheck = transform.Find("groundCheck");
    		anim = GetComponent();
    		col = GetComponent();
    	}
    
    	void Update()
    	{
    		/*walled = Physics.Raycast(transform.position + (transform.up * 2f), transform.forward, 0.2f, 1 << LayerMask.NameToLayer("Wall"));
    		if (walled)
    			transform.position = transform.position - transform.forward *0.2f;*/
    		/*if (walledRight)
    			transform.position = transform.position - Vector3.right *0.2f;*/
    		// If the jump button is pressed and the player is grounded then the player should jump.
    		if (Input.GetButtonDown ("Jump") && grounded) {
    				jump = true;
    				anim.SetTrigger ("Jump");
    		}
    	}
    	
    	
    	void FixedUpdate ()
    	{
    
    		/*RaycastHit hit;
    		CapsuleCollider charColl = GetComponent ();
    		vOffset = new Vector3 (0, (charColl.radius + 0.1f), 0);
    		Vector3 p1 = transform.position + vOffset;
    		Vector3 p2 = p1 + Vector3.up * charColl.height;*/
    		// The player is grounded if a Raycast hits anything on the ground layer.
    		grounded = Physics.Raycast(transform.position + (transform.up * 0.2f), -transform.up, 0.2f, 1 << LayerMask.NameToLayer("Ground"));
    		// The player is Walled if a linecast hits anything on the ground layer.
    		//walled = Physics.CapsuleCast(p1, p2, charColl.radius + 0.1f, transform.forward, out hit, 0, layerMask);
    		//walledLeft = Physics.Raycast (transform.position + (Vector3.up * 2f), -Vector3.right, 0.2f, 1 << LayerMask.NameToLayer("Wall"));
    		walled = Physics.Raycast(transform.position + (transform.up * 2f), transform.forward, 0.2f, 1 < maxSpeed)
    			// ... set the player's velocity to the maxSpeed in the x axis.
    							rigidbody.velocity = new Vector3 (Mathf.Sign (rigidbody.velocity.x) * maxSpeed, rigidbody.velocity.y);
    
    						// if the player is jumping and is next to a wall, stop adding force.
    						if (walled && !grounded){
    							if (h < -0.01f)
    								rigidbody.velocity = new Vector3 (0, rigidbody.velocity.y);
    							else if(h > 0.01f)
    								rigidbody.velocity = new Vector3 (0, rigidbody.velocity.y);
    								
    						}
    						// If the input is moving the player right and the player is facing left...
    						if (h > 0 && !facingRight)
    			// ... flip the player.
    								Flip ();
    		// Otherwise if the input is moving the player left and the player is facing right...
    		else if (h < 0 && facingRight)
    			// ... flip the player.
    								Flip ();
    
    						// If the player should jump...
    						if (jump) {
    								// Set the Jump animator trigger parameter.
    								
    			
    								/*// Play a random jump audio clip.
    			int i = Random.Range(0, jumpClips.Length);
    			AudioSource.PlayClipAtPoint(jumpClips_, transform.position);*/_
 
 *								// Add a vertical force to the player.*
 *								rigidbody.AddRelativeForce (new Vector3 (0f, jumpForce, 0f));*
 
 *								// Make sure the player can't jump again until the jump conditions from Update are satisfied.*
 *								jump = false;*
 *						}*
 *						if (Input.GetButtonDown ("Dash"))*
 *								anim.SetTrigger ("DoDash");*
 *						col.height = anim.GetFloat ("colliderHeight");*
 *						col.center = new Vector3 (0, anim.GetFloat ("colliderTranslateY"), 0);*
 
 *						if (Input.GetButtonDown ("Attack"))*
 *								anim.SetTrigger ("DoAttack");*
 *		}*
 *	}*
 _	/*void OnDrawGizmos (){_
 *		CapsuleCollider charColl = GetComponent ();*
 _		Vector3 p1 = transform.position + charColl.center + Vector3.up * -charColl.height * 0.4f;_
 _		Vector3 p2 = p1 + Vector3.up * (charColl.height - 0.5f);_
 *		Gizmos.DrawSphere (p1, charColl.radius);*
 *		Gizmos.DrawSphere (p2, charColl.radius);*
 _		}*/_
 
 *	void Flip ()*
 *	{*
 *		// Switch the way the player is labelled as facing.*
 *		facingRight = !facingRight;*
 
 *		// Multiply the player's x local scale by -1.*
 *		Quaternion theRotation = transform.localRotation;*
 _		theRotation.y *= -1;_
 *		transform.localRotation = theRotation;*
 *	}*
 *}*
*`*
*`
*
Detritus answered 1/9, 2023 at 10:29 Comment(0)
G
0

Didn’t proof your code (sorry). Seems like if the only problem is this getting-stuck-to-walls thing, you could add a check to determine whether you’re immediately adjacent to a wall and ignore any input to add force in the wall’s direction.

Generative answered 3/11, 2014 at 2:40 Comment(1)

There's a raycast I use for that in the script. There's another problem where if the character stands too close to a wall, it can't jump because of what I assume to be friction.

Detritus
Z
0

I didnt run your code but here are some potential problems.

you need two raycasts to check if walled. One for the head and one for the feet.
maybe the raycast is too short, make it so that there will always be a little gap between the collider an the wall.
make the raycast origins as child objects of your char,at the edge of the collider, better to debug.
Is walled true when you stick to walls?
you disable the speed when it is >0.01, why not >0? Even a speed of 0.009 might get you stuck.

Zweig answered 1/12, 2014 at 9:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.