Hey guys, Not sure how to work around this problem:
The idea behind my barrier:
When i place a barrier on the ground (I’ve temporarily just implemented it so it’s placed under the player whenever I drop any item - hence the reason dropping a health potion spawn the barrier) I want the player to be able to walk around in it until they “leave”. When they leave, the player is taken out of a list and no longer allowed to stand in the barrier. All other players who aren’t standing on the spot it’s instantiated never are able to walk in it.
Here’s the barrier mechanics implementation: Screen capture - 9dc64240851ee620544751869fbc77c7 - Gyazo
So I’ve actually got a great implementation except for one thing… When I try to move to a location that the barrier would block, I get the jitters because it can not longer move there. I want it to get stuck on the barrier, with no rerouting. Example of the jitters: Screen capture - b4c9ebb2f2f772a42853f12d0bf0b308 - Gyazo
So I’ve tried a lot of different things but they just don’t seem to work. I have to keep a special case in mind: When I run into an edge on the barrier, I need to figure out the direction it came from and only edit the x or the z value.
For example, the player and the barrier collide just on the corner here: Screenshot - dd2bae636012f3d7bb098b777f373c4a - Gyazo
-The barrier collider is 1x1x1
-The player collider is 1x1x1
I can’t just stop the player and then set the destination to the player.transform.position because it’s already “partially inside” the barrier because it OnTriggerEnter is executed
Here’s the code that I’m using. The portion that deals with setting the agent transform is in the StopPlayer function:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Barrier : MonoBehaviour
{
private List<GameObject> playersInbarrierAtStart;
void Start()
{
playersInbarrierAtStart = new List<GameObject>();
//Take either x or z, doesn't matter since both are the same size.
float colliderWidthAndLength = gameObject.GetComponent<Collider>().bounds.size.x;
float colliderHeight = gameObject.GetComponent<Collider>().bounds.size.y;
Vector3 colliderHalfExtents = new Vector3(colliderWidthAndLength, colliderHeight, colliderWidthAndLength);
Collider[] collidersInsideBox = Physics.OverlapBox(transform.position, colliderHalfExtents, Quaternion.identity);
for (int index = 0; index < collidersInsideBox.Length; index++)
{
Collider Co = collidersInsideBox[index];
//we only want to add each player once (there are two colliders per player)
if (Co.gameObject.tag == "Player" && !Co.isTrigger)
{
//Found a player, add it to the list.
Debug.Log("(Start)Added: " + collidersInsideBox[index].gameObject);
playersInbarrierAtStart.Add(collidersInsideBox[index].gameObject);
Debug.Log(playersInbarrierAtStart.Count);
}
}
}
private void OnTriggerEnter(Collider other)
{
GameObject gameObjectInsideBarrier = other.gameObject;
StopPlayer(other);
//player wasn't standing in spot barrier was instantiated at, toggle isKinematic.
if (gameObjectInsideBarrier.tag == "Player")
{
bool playerRBKinematic = gameObjectInsideBarrier.GetComponent<Rigidbody>().isKinematic;
if (!playersInbarrierAtStart.Contains(other.gameObject) && playerRBKinematic)
{
Debug.Log("(Enter) isKinematic set to false: " + gameObjectInsideBarrier);
gameObjectInsideBarrier.GetComponent<Rigidbody>().isKinematic = false;
}
}
}
private void OnTriggerExit(Collider other)
{
Rigidbody otherRB = other.gameObject.GetComponent<Rigidbody>();
if (other.gameObject.tag == "Player" && !otherRB.isKinematic)
{
Debug.Log("Set to true");
otherRB.isKinematic = true;
}
for(int index = 0; index < playersInbarrierAtStart.Count; index++)
{
Debug.Log(index);
if(playersInbarrierAtStart.Contains(other.gameObject))
{
Debug.Log("Removed: " + other.gameObject + " Count: "+ playersInbarrierAtStart.Count);
playersInbarrierAtStart.Remove(other.gameObject);
Debug.Log(" Count: " + playersInbarrierAtStart.Count);
}
}
}
private void StopPlayer(Collider player)
{
NavMeshAgent playerAgent = player.gameObject.GetComponent<NavMeshAgent>(); //.isStopped = true;
playerAgent.isStopped = true;
Vector3 dir = (gameObject.transform.position - player.transform.position).normalized;
Vector3 offset = new Vector3(Mathf.Round(dir.x + .3f), 0, Mathf.Round(dir.z + .3f));
//I know the offset isn't correct, just was playing around with different values to try and make it work.
Debug.Log(player.gameObject.transform.position + offset);
playerAgent.destination = player.gameObject.transform.position + offset;//player.gameObject.transform.position + offset;
playerAgent.isStopped = false;
//Vector3 barricadeCenter = gameObject.GetComponent<Collider>().bounds.center;
//Vector3 finalDestination = barricadeCenter;
//float xOffset = barricadeCenter.x - player.transform.position.x;
//float zOffset = barricadeCenter.z - player.transform.position.z;
///**Take the smaller value.
// * We only want to set either x or z, not both.
// * We set the smaller value since we can get stuck on the corner of the barrier
// * */
//if (Mathf.Abs(xOffset) < Mathf.Abs(zOffset))
//{
// finalDestination.z = barricadeCenter.z - zOffset - .01f;
//}
//else
//{
// finalDestination.x = barricadeCenter.x - xOffset -.01f;
//}
//playerAgent.destination = finalDestination;
//Debug.Log(finalDestination);
}
}