My code is a little more complex because I’ve created a system for objects pushing other objects, to go along with my dungeon puzzle theme. The character does a sweeptest forward, with a magnitude of 20, and if the objects that are hit are not pushable it doesn’t move, it they are pushable it tries to push them and then moves accordingly.
It determines whether or not something is pushable by the object tag. All the objects I have fallen through have the tag “Fixture” and nowhere are they allowed to be pushed or moved through. The collider on my 100x200x100 character is set to 0.99x0.99x0.99 and the move magnitude of any object is 20. All fixtures have their colliders set to 1x1x1. This means that I should have a threshold of 1 between the character and the ground at any given time and a threshold of 0.5f between any wall. When I last had the error in the editor I moved the wall/floor in all directions by 5 and it had no impact on whether or not the character passed through. On the wall I was able to pass through from all directions. If it was a clipping issue, and especially given I had moved the wall, it should have only passed through from half the directions.
If the player is cleared to move it jumps forward 20. This is a small enough unit in my game that it still appears smooth, so I don’t need to use lerping.
When the error happens it typically only happens to one object in the area. As there are very few floor objects in the game, about 4 per room and about 7 rooms on average, there aren’t many opportunities for it to fail.
public void GetCheckDirection(string givenString) {
string currentPushingObject = "character";
NetworkInstanceId currentNetId = netId;
Vector3 moveVector = Vector3.zero;
if (optionsScript.menu == false) {
if (givenString == "y") {
moveVector = -transform.up;
currentPushingObject = "gravity";
currentNetId = gravityNetId;
} else if (givenString == "x") {
moveVector = Vector3.right * currentXAxis;
} else if (givenString == "z") {
moveVector = Vector3.forward * currentZAxis;
}
}
List<Collider> blankList = new List<Collider>();
int givenWeight = 0;
CheckMovement(moveVector, "check", currentPushingObject, currentNetId, ref blankList, ref givenWeight);
}
public bool CheckMovement(Vector3 givenVector, string givenString, string pushingObject, NetworkInstanceId givenNetId, ref List<Collider> givenTestedObjects, ref int givenWeight) {
if (pushingObject != "door") {
allowedToMove = false;
}
if (givenVector != Vector3.zero) {
bool belowThingsHit = true;
givenVector = Vector3.Normalize(givenVector);
Vector3 originalVector = givenVector;
if (givenString == "check") {
//Update Movement Vector To Use Ladders
if (ladderScript.downDirections.Count > 0) {
givenVector = ladderScript.LadderMovement(givenVector);
}
//Verify Object Is On Another Object Before Moving XZ
//Some Scenarios Don't Require Checking Objects Below
bool checkBelow = true;
if (ladderScript.downDirections.Count == 0 && givenVector == -Vector3.up) {
checkBelow = false;
} else if (givenVector == Vector3.up) {
checkBelow = false;
} else if (ladderScript.downDirections.Count != 0 && givenVector != -Vector3.up) {
checkBelow = false;
} else if (checkBelow == true) {
//Baring Some Objects, Check Below For Another Object
if (ladderScript.downDirections.Count == 0 || givenVector != -Vector3.up) {
belowThingsHit = false;
}
RaycastHit[] belowThings = GetComponent<Rigidbody>().SweepTestAll(-transform.up, speed, QueryTriggerInteraction.Ignore);
foreach (RaycastHit item in belowThings) {
if (item.collider.tag != "Cube Wall" && item.collider.tag != "Character") {
if (checkBelow == true) {
belowThingsHit = true;
if (ladderScript.downDirections.Count != 0) {
givenVector = originalVector;
}
break;
}
}
}
}
}
if (belowThingsHit == true && givenVector != Vector3.zero) {
//Check If Moving Will Result In A Collision, Or Possibly Push Cubes
//bool hitSomething = false;
//bool onlyPushableCube = gameObject.GetComponent<PushCube>().CheckHits(pushingObject, givenVector*speed, out hitSomething, ladderScript.downDirections.Count);
//If No Collision In The Way, And Not Trying To Freefall Whilst On Ladder
bool freeMove = ladderScript.downDirections.Count == 0 || originalVector != Vector3.down;
bool freePush = playerabilities.pushCube == true && givenVector != Vector3.up;
bool shouldMove = gameObject.GetComponent<PushCube>().CheckCubes(givenVector*speed, givenString, pushingObject, givenNetId, ref givenTestedObjects, ref givenWeight, freeMove, freePush);
if (shouldMove) {
if (givenString == "check") {
allowedToMove = true;
allowedToMoveVector = givenVector;
} else if (givenString == "set") {
allowedToMove = true;
allowedToMoveVector = givenVector;
}
return true;
} else if (givenString == "check" || givenString == "set") {
allowedToMove = false;
}
}
}
return false;
}
public bool CheckCubes(Vector3 moveVector, string givenString, string pushingObject, NetworkInstanceId givenNetId, ref List<Collider> testedObjects, ref int givenWeight, bool characterFreeMove = true, bool characterFreePush = true, int ladderDownCount = 0) {
//Checking If All The Cubes Are Able To Move
if (testedObjects.Count == 0) {
if (gameObject.GetComponent<Collider>() != null) {
testedObjects.Add(gameObject.GetComponent<Collider>());
}
}
if (gameObject.tag == "Pushable Cube" && gameObject.GetComponent<XZNetworkedCube>().hasMovementPlan == true) {
moveVector = Vector3.Normalize(moveVector) * gameObject.GetComponent<XZNetworkedCube>().GetSpeed();
}
hitThings = GetComponent<Rigidbody>().SweepTestAll(moveVector, moveVector.magnitude, QueryTriggerInteraction.Ignore);
List<Collider> newObjects = new List<Collider>();
bool hitSomething = false;
bool allCubesCanMove = true;
foreach (RaycastHit item in hitThings) {
if (item.collider.tag == "Pushable Collider") {
hitSomething = true;
if (item.collider.transform.parent.GetComponent<XZNetworkedCube>().movingNetId != givenNetId.ToString()) {
allCubesCanMove = false;
break;
}
} else if (item.collider.tag == "Pushable Cube") {
if (pushingObject == "door" || pushingObject == "character" || pushingObject == "gravity") {
if (testedObjects.Contains(item.collider) == false) {
testedObjects.Add(item.collider);
newObjects.Add(item.collider);
XZNetworkedCube movingScript = item.collider.GetComponent<XZNetworkedCube>();
if (pushingObject == "gravity" || movingScript.movingNetId != gravityNetId.ToString() || movingScript.hasMovementPlan != true) {
hitSomething = true;
bool cubeCanMove = movingScript.CheckMovement(moveVector, "pushCheck", pushingObject, givenNetId, ref testedObjects, ref givenWeight);
if (cubeCanMove == false) {
allCubesCanMove = false;
break;
} else {
givenWeight += movingScript.GetComponent<WeightCalculatorStorer>().weightCalculatorScript.weight;
}
}
}
} else {
hitSomething = true;
allCubesCanMove = false;
}
} else if (item.collider.tag == "Character") {
if (pushingObject == "door") {
if (testedObjects.Contains(item.collider) == false) {
testedObjects.Add(item.collider);
newObjects.Add(item.collider);
hitSomething = true;
XZNetworkedPlayer movingScript = item.collider.GetComponent<XZNetworkedPlayer>();
bool characterCanMove = movingScript.CheckMovement(moveVector, "pushCheck", "door", givenNetId, ref testedObjects, ref givenWeight);
if (characterCanMove == false) {
allCubesCanMove = false;
break;
} else {
givenWeight += movingScript.GetComponent<WeightCalculatorStorer>().weightCalculatorScript.weight;
}
}
} else {
if (((pushingObject == "character" || pushingObject == "gravity") && (characterFreeMove == false || Vector3.Normalize(moveVector) != Vector3.down)) || (pushingObject != "character" && pushingObject != "gravity")) {
hitSomething = true;
allCubesCanMove = false;
break;
}
}
} else {
if (item.collider.tag != "Bullet") {
if (pushingObject == "character") {
if (item.collider.tag != "Cube Wall" && (Vector3.Normalize(moveVector) != -Vector3.up || item.collider.tag != "Character" || ladderDownCount != 0)) {
hitSomething = true;
allCubesCanMove = false;
break;
}
} else if (pushingObject == "door") {
if (item.collider.tag != "Cube Wall" && item.collider.tag != "Player Wall") {
hitSomething = true;
allCubesCanMove = false;
break;
}
} else {
hitSomething = true;
allCubesCanMove = false;
break;
}
}
}
if (((pushingObject == "door" && givenWeight > optionsScript.doorMaxWeight) || (pushingObject == "character" && givenWeight > optionsScript.characterMaxWeight)) && Vector3.Normalize(moveVector) != Vector3.down && allCubesCanMove == true) {
allCubesCanMove = false;
break;
}
}
//If Cubes Can Move, And Ocassionaly Moves Them
if (allCubesCanMove == true) {
if (pushingObject != "character" || (pushingObject == "character" && ((hitSomething == false) || (characterFreePush == true && allCubesCanMove == true && hitSomething == true)))) {
if (givenString == "set") {
testedObjects.Reverse();
foreach (Collider item in testedObjects) {
if (item.tag == "Pushable Cube") {
XZNetworkedCube movingScript = item.GetComponent<XZNetworkedCube>();
movingScript.SetMovingNetId(givenNetId);
}
}
foreach (Collider item in testedObjects) {
if (item.gameObject != gameObject) {
if (item.tag == "Pushable Cube") {
XZNetworkedCube movingScript = item.GetComponent<XZNetworkedCube>();
movingScript.MakeMovementPlan(moveVector, pushingObject, givenNetId, "pushed");
} else if (item.tag == "Character" && pushingObject == "door") {
XZNetworkedPlayer movingScript = item.GetComponent<XZNetworkedPlayer>();
movingScript.TryMoving(moveVector, pushingObject, givenNetId, "pushed");
}
}
}
}
return true;
}
}
return false;
}