Reputation: 33
I'm trying to make a simple sliding puzzle game in unity and have put together some code that works for moving the blocks. One parameter that's a must is, once the block has stared moving I'd like it to no longer accept input until it has come to a stop. I've got this too work however if the block is in contact with a wall and I press for the block to go towards that wall again, the isStopped bool is set permanently to false and the block can't be moved again (you can see this in the bottom right of the gif). Am I doing something stupid? Is there an easy way to circumvent this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Moving : MonoBehaviour
{
private Rigidbody2D rb;
private float speed = 100;
public bool isStopped = true;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.W) && isStopped)
{
rb.AddForce(Vector2.up * speed );
isStopped = false;
}
if(Input.GetKeyDown(KeyCode.S) && isStopped)
{
rb.AddForce(Vector2.down * speed );
isStopped = false;
}
if(Input.GetKeyDown(KeyCode.A) && isStopped)
{
rb.AddForce(Vector2.left * speed );
isStopped = false;
}
if(Input.GetKeyDown(KeyCode.D) && isStopped)
{
rb.AddForce(Vector2.right * speed );
isStopped = false;
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
isStopped = true;
}
/* private void OnCollisionStay2D(Collision2D collision)
{
isStopped = true;
} */
}
Upvotes: 1
Views: 100
Reputation: 964
Example: Make an enum class (or see if an existing one exists) representing direction.
namespace Blah.Blah.Blah;
public enum Direction
{
Up,
Down,
Left,
Right,
}
Then we need a property which tracks the available movement directions. In this case it's easier because we have a rectangular area. We use this set to verify that the direction movement is available for each condition.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Moving : MonoBehaviour
{
private Rigidbody2D rb;
private float speed = 100;
public bool isStopped = true;
public HashSet<Direction> availableMovements = new HashSet<Direction>();
void Start()
{
rb = GetComponent<Rigidbody2D>();
// Need to initialize available movements (Assuming we start without touching any wall)
availableMovements.Add(Direction.Up);
availableMovements.Add(Direction.Down);
availableMovements.Add(Direction.Left);
availableMovements.Add(Direction.Right);
}
void Update()
{
if(Input.GetKeyDown(KeyCode.W) && isStopped && availableMovements.Contains(Direction.Up))
{
rb.AddForce(Vector2.up * speed );
isStopped = false;
availableMovements.Remove(Direction.Up);
availableMovements.Add(Direction.Down);
}
if(Input.GetKeyDown(KeyCode.S) && isStopped && availableMovements.Contains(Direction.Down))
{
rb.AddForce(Vector2.down * speed );
isStopped = false;
availableMovements.Remove(Direction.Down);
availableMovements.Add(Direction.Up);
}
if(Input.GetKeyDown(KeyCode.A) && isStopped && availableMovements.Contains(Direction.Left))
{
rb.AddForce(Vector2.left * speed );
isStopped = false;
availableMovements.Remove(Direction.Left);
availableMovements.Add(Direction.Right);
}
if(Input.GetKeyDown(KeyCode.D) && isStopped && availableMovements.Contains(Direction.Right))
{
rb.AddForce(Vector2.right * speed );
isStopped = false;
availableMovements.Remove(Direction.Right);
availableMovements.Add(Direction.Left);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
isStopped = true;
}
}
Upvotes: 1
Reputation: 841
I think you missed a small thing. Try this to see if it lets you continue motion if you run into a wall:
//create a way to disable input
public class GameManager : MonoBehaviour
{
public static bool IsInputEnabled = true;
}
Preventing motion is a second issue if this first part works we solve it one way and if not, another.
I'd recommend changing your if statements to a case block also for what you are doing here. Since you should only ever move cardinal directions and there isn't a need to know if someone is moving left AND up, case would work.
Upvotes: 0