Hello! I’m making progress on my collision system, and now the player can move and collide. However, I’m having some problems with the movement, which I am assuming are due to the way I’m handling the numbers. I’ve messed around with it for a bit and I’m not entirely sure what I’m doing wrong, but I figure I’m just missing something obvious.
Here’s the base collision detection script, this one seems to do it’s job without any problems.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class Collide : MonoBehaviour
{
//eventually going to replace this with a collection of all colliders in the scene or something for performance
//public GameObject self;
//Collider2D selfCollider; deprecated due to new overlapBox method
//vector2 offset and position for use in MoveX/Y
Vector2 offset;
//Vector2 position;
//Establish hitbox sizes, this should be removed and passed in through the player class once that's set up
//private Vector2 idleHitbox = new Vector2(0.6f, 1.3f);
// Start is called before the first frame update
void Start()
{
//Vector3 position3d = self.transform.position;
//Vector2 position = position3d;
}
// Update is called once per frame
void Update()
{
//in the final draft this should not be called through the collide, but through the classes inheriting from it
}
//this needs to be tweaked so that an offset can be passed in. This way, the Actor class can pass in the Sign of 'move', letting it check ahead of itself by a certain offset for collisions.
public bool CollideAt(Vector2 collider, Vector2 position, Vector2 offset)
{
//you'll want to edit this at some point so that the hitboxes can be passed in through the player class, because right now, this is just bad.
bool collisionTest = Physics2D.OverlapBox(position + offset, collider, 0);
//bool collisionTest = Physics2D.OverlapBox(self.transform.position/*+ offset*/, new Vector2(0.6f, 1.3f), 0); //original standalone collision detection code
Debug.Log(/*self.transform.position + " — " + */collisionTest);
return collisionTest;
}
}
And here’s the Actor class script I’m testing, which inherits from Collide.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Actor : Collide
{
private float xRemainder;
private float yRemainder;
public delegate void Action(string logText);
public Action onCollide;
Vector2 actorCollider = new Vector2(1, 1);
Vector2 actorPosition;
// Start is called before the first frame update
void Start()
{
onCollide = OnCollide;
onCollide("PHWEEE");
////This is the groundwork for the movement system. We take the 3d pos, pass it to a varaible which modifies it, then return the modified version to move.
//this.transform.position = new Vector3(0, 0, 0);
actorPosition = this.transform.position;
//actorPosition.x += 0.8f;
//this.transform.position = actorPosition;
//MoveX(0.1f, OnCollide);
}
// Update is called once per frame
void Update()
{
//Vector3 position3d = this.transform.position;
//actorPosition = position3d;
if (Input.GetKey(KeyCode.RightArrow))
{
// Debug.Log("right");
// actorPosition = this.transform.position;
// actorPosition.x += 0.1f;
// this.transform.position = actorPosition;
MoveX(1, OnCollide);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
// Debug.Log("left");
// actorPosition = this.transform.position;
// actorPosition.x += -0.1f;
// this.transform.position = actorPosition;
MoveX(-1, OnCollide);
}
if (Input.GetKey(KeyCode.UpArrow))
{
// Debug.Log("right");
// actorPosition = this.transform.position;
// actorPosition.x += 0.1f;
// this.transform.position = actorPosition;
MoveY(1, OnCollide);
}
if (Input.GetKey(KeyCode.DownArrow))
{
// Debug.Log("left");
// actorPosition = this.transform.position;
// actorPosition.x += -0.1f;
// this.transform.position = actorPosition;
MoveY(-1, OnCollide);
}
}
public void MoveX(float amount, Action onCollide)
{
int intAmount = (int)amount * 10;
xRemainder += amount;
int move = Math.Sign(xRemainder);
Debug.Log(move);
if (move != 0)
{
xRemainder -= move;
int sign = Math.Sign(move);
Debug.Log("Sign: " + sign);
//float signInUnits = sign / 10;
while (move != 0)
{
//if (!collideAt(solids, Position + new Vector2(sign, 0))
//{
// //No solid immediately beside us
// Position.X += sign;
// move -= sign;
//}
//else
//{
// //Hit a solid!
// if (onCollide != null)
// onCollide();
// break;
//}
if (!CollideAt(actorCollider, actorPosition, new Vector2(sign, 0)/*offset*/))
{
//No solid immediately beside us
actorPosition.x += sign;
move -= sign;
this.transform.position = actorPosition;
Debug.Log("Actor Position: " + actorPosition);
}
else
{
Debug.Log("Collision Detected");
this.transform.position = actorPosition;
break;
}
}
}
}
public void MoveY(float amount, Action onCollide)
{
int intAmount = (int)amount * 10;
yRemainder += amount;
int move = Math.Sign(yRemainder);
Debug.Log(move);
if (move != 0)
{
yRemainder -= move;
int sign = Math.Sign(move);
Debug.Log("Sign: " + sign);
//float signInUnits = sign / 10;
while (move != 0)
{
//if (!collideAt(solids, Position + new Vector2(sign, 0))
//{
// //No solid immediately beside us
// Position.Y += sign;
// move -= sign;
//}
//else
//{
// //Hit a solid!
// if (onCollide != null)
// onCollide();
// break;
//}
if (!CollideAt(actorCollider, actorPosition, new Vector2(0, sign)/*offset*/))
{
//No solid immediately beside us
actorPosition.y += sign;
move -= sign;
this.transform.position = actorPosition;
Debug.Log("Actor Position: " + actorPosition);
}
else
{
Debug.Log("Collision Detected");
this.transform.position = actorPosition;
break;
}
}
}
}
public void OnCollide(string logText)
{
//Debug.Log(logText);
}
}
The way it’s currently set up, it works fine if you move in integers, but anything less than that and it starts acting up. I need to change it so that everything moves in tenths, but I’m not entirely sure how to go about doing this.
EDIT: If it helps, I’m going off of this resource (https://mattmakesgames.tumblr.com/post/127890619821/towerfall-physics), and creating the missing pieces based on the descriptions of what they need to do.