功能:
计算角色/怪物走到目标,如果有墙就再墙前停止,防止一直怼墙走现象。
思路:
1. θ角 = 入射线(self - target) 与 法线(raycastHit.normal) 的夹角度(V3.angle)
2. 距墙停止距离 = 自身半径R / cosθ角
3. |应走向量| = 走到墙前向量.长度(magnitude) - 距墙停止距离
4. 应走向量 = 到墙向量.单位向量 * |应走向量|
限制:
①不能是斜着的墙或人
②地形是平面
③不能太小的阻挡物,太细的夹角需要增加一次计算
实验截图:
橙色圆柱是角色,绿色是要走到的目标位置,计算结果是灰色圆柱
上码:
public class test : MonoBehaviour
{
public GameObject Self;
public GameObject Fake;
public GameObject Target;
public float width;
public float rayAngle;
public float rayDirectValue;
public float realGetLenght;
public Vector3 rayVector;
public Vector3 realGetVector;
public float offerAngle;
public float offerSin;
public float offerCos;
public float offerXValue;
public float offerZValue;
void Start()
{
width = Self.GetComponent<CapsuleCollider>().radius * Self.transform.localScale.x;
}
void Update()
{
Vector3 wantPos = Target.transform.position;
Vector3 realGetPos = Vector3.zero;
RaycastHit raycastHit = new RaycastHit();
Ray wallCheck = new Ray(Self.transform.position, Target.transform.position - Self.transform.position);
if (Physics.Raycast(wallCheck, out raycastHit, Vector3.Distance(Target.transform.position, Self.transform.position) + 8, 1 << LayerMask.NameToLayer("Ground")))
{
rayAngle = Vector3.Angle(Self.transform.position - Target.transform.position, raycastHit.normal);
rayDirectValue = width / Mathf.Cos(Mathf.PI / 180 * rayAngle);
rayVector = raycastHit.point - Self.transform.position;
realGetLenght = rayVector.magnitude - rayDirectValue;
realGetVector = rayVector.normalized * realGetLenght;
realGetPos = new Vector3(
Self.transform.position.x + realGetVector.x,
Self.transform.position.y,
Self.transform.position.z + realGetVector.z);
}
else
realGetPos = wantPos;
Fake.transform.position = realGetPos;
Debug.DrawLine(Self.transform.position, wantPos, Color.red);
Debug.DrawLine(Self.transform.position, realGetPos, Color.blue);
}
}