我使用的是来自矢量的第三人称控制器,在示例场景中,它为相机提供了碰撞检测,但它仍然会穿过墙壁一点。(你可以看到墙的另一边。)有人能指出我正确的方向,如何解决这个问题?
//Check if desired target position is not blocked
if (CullingRayCast(desired_cPos, oldPoints, out hitInfo, distance + 0.2f, cullingLayer, Color.blue))
{
// distance = hitInfo.distance; //WORKING BUT WALLS GLITCHING DUE TO HEIGHT
distance = hitInfo.distance - 0.2f;
if (distance < defaultDistance)
{
var t = hitInfo.distance;
t -= cullingMinDist;
t /= cullingMinDist;
currentHeight = Mathf.Lerp(cullingHeight, height, Mathf.Clamp(t, 0.0f, 1.0f));
current_cPos = currentTargetPos + new Vector3(0, currentHeight, 0);
}
如果我把距离改为hit.Info.distance而不是hitInfo。如上图所示,距离-0.2f,它就会开始出现故障。
using Invector;
using UnityEngine;
public class vThirdPersonCamera : MonoBehaviour
{
#region inspector properties
public Transform target;
[Tooltip("Lerp speed between Camera States")]
public float smoothCameraRotation = 12f;
[Tooltip("What layer will be culled")]
public LayerMask cullingLayer = 1 << 0;
[Tooltip("Debug purposes, lock the camera behind the character for better align the states")]
public bool lockCamera;
public float rightOffset = 0f;
public float defaultDistance = 2.5f;
public float height = 1.4f;
public float smoothFollow = 10f;
public float xMouseSensitivity = 3f;
public float yMouseSensitivity = 3f;
public float yMinLimit = -40f;
public float yMaxLimit = 80f;
#endregion
#region hide properties
[HideInInspector]
public int indexList, indexLookPoint;
[HideInInspector]
public float offSetPlayerPivot;
[HideInInspector]
public string currentStateName;
[HideInInspector]
public Transform currentTarget;
[HideInInspector]
public Vector2 movementSpeed;
private Transform targetLookAt;
private Vector3 currentTargetPos;
private Vector3 lookPoint;
private Vector3 current_cPos;
private Vector3 desired_cPos;
private Camera _camera;
private float distance = 5f;
private float mouseY = 0f;
private float mouseX = 0f;
private float currentHeight;
private float cullingDistance;
private float checkHeightRadius = 0.4f;
private float clipPlaneMargin = 0f;
private float forward = -1f;
private float xMinLimit = -360f;
private float xMaxLimit = 360f;
private float cullingHeight = 0.2f;
private float cullingMinDist = 0.1f;
#endregion
void Start()
{
Init();
}
public void Init()
{
if (target == null)
return;
_camera = GetComponent<Camera>();
currentTarget = target;
currentTargetPos = new Vector3(currentTarget.position.x, currentTarget.position.y + offSetPlayerPivot, currentTarget.position.z);
targetLookAt = new GameObject("targetLookAt").transform;
targetLookAt.position = currentTarget.position;
targetLookAt.hideFlags = HideFlags.HideInHierarchy;
targetLookAt.rotation = currentTarget.rotation;
mouseY = currentTarget.eulerAngles.x;
mouseX = currentTarget.eulerAngles.y;
distance = defaultDistance;
currentHeight = height;
}
void FixedUpdate()
{
if (target == null || targetLookAt == null) return;
CameraMovement();
}
/// <summary>
/// Set the target for the camera
/// </summary>
/// <param name="New cursorObject"></param>
public void SetTarget(Transform newTarget)
{
currentTarget = newTarget ? newTarget : target;
}
public void SetMainTarget(Transform newTarget)
{
target = newTarget;
currentTarget = newTarget;
mouseY = currentTarget.rotation.eulerAngles.x;
mouseX = currentTarget.rotation.eulerAngles.y;
Init();
}
/// <summary>
/// Convert a point in the screen in a Ray for the world
/// </summary>
/// <param name="Point"></param>
/// <returns></returns>
public Ray ScreenPointToRay(Vector3 Point)
{
return this.GetComponent<Camera>().ScreenPointToRay(Point);
}
/// <summary>
/// Camera Rotation behaviour
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public void RotateCamera(float x, float y)
{
// free rotation
mouseX += x * xMouseSensitivity;
mouseY -= y * yMouseSensitivity;
movementSpeed.x = x;
movementSpeed.y = -y;
if (!lockCamera)
{
mouseY = vExtensions.ClampAngle(mouseY, yMinLimit, yMaxLimit);
mouseX = vExtensions.ClampAngle(mouseX, xMinLimit, xMaxLimit);
}
else
{
mouseY = currentTarget.root.localEulerAngles.x;
mouseX = currentTarget.root.localEulerAngles.y;
}
}
/// <summary>
/// Camera behaviour
/// </summary>
void CameraMovement()
{
if (currentTarget == null)
return;
distance = Mathf.Lerp(distance, defaultDistance, smoothFollow * Time.deltaTime);
cullingDistance = Mathf.Lerp(cullingDistance, distance, Time.deltaTime);
var camDir = (forward * targetLookAt.forward) + (rightOffset * targetLookAt.right);
camDir = camDir.normalized;
var targetPos = new Vector3(currentTarget.position.x, currentTarget.position.y + offSetPlayerPivot, currentTarget.position.z);
currentTargetPos = targetPos;
desired_cPos = targetPos + new Vector3(0, height, 0);
current_cPos = currentTargetPos + new Vector3(0, currentHeight, 0);
RaycastHit hitInfo;
ClipPlanePoints planePoints = _camera.NearClipPlanePoints(current_cPos + (camDir * (distance)), clipPlaneMargin);
ClipPlanePoints oldPoints = _camera.NearClipPlanePoints(desired_cPos + (camDir * distance), clipPlaneMargin);
//Check if Height is not blocked
if (Physics.SphereCast(targetPos, checkHeightRadius, Vector3.up, out hitInfo, cullingHeight + 0.2f, cullingLayer))
{
var t = hitInfo.distance - 0.2f;
t -= height;
t /= (cullingHeight - height);
cullingHeight = Mathf.Lerp(height, cullingHeight, Mathf.Clamp(t, 0.0f, 1.0f));
}
//Check if desired target position is not blocked
if (CullingRayCast(desired_cPos, oldPoints, out hitInfo, distance + 0.2f, cullingLayer, Color.blue))
{
// distance = hitInfo.distance; //WORKING BUT WALLS GLITCHING DUE TO HEIGHT
distance = hitInfo.distance - 0.2f;
if (distance < defaultDistance)
{
var t = hitInfo.distance;
t -= cullingMinDist;
t /= cullingMinDist;
currentHeight = Mathf.Lerp(cullingHeight, height, Mathf.Clamp(t, 0.0f, 1.0f));
current_cPos = currentTargetPos + new Vector3(0, currentHeight, 0);
}
}
else
{
currentHeight = height;
}
//Check if target position with culling height applied is not blocked
if (CullingRayCast(current_cPos, planePoints, out hitInfo, distance, cullingLayer, Color.cyan)) distance = Mathf.Clamp(cullingDistance, 0.0f, defaultDistance);
var lookPoint = current_cPos + targetLookAt.forward * 2f;
lookPoint += (targetLookAt.right * Vector3.Dot(camDir * (distance), targetLookAt.right));
targetLookAt.position = current_cPos;
Quaternion newRot = Quaternion.Euler(mouseY, mouseX, 0);
targetLookAt.rotation = Quaternion.Slerp(targetLookAt.rotation, newRot, smoothCameraRotation * Time.deltaTime);
transform.position = current_cPos + (camDir * (distance));
var rotation = Quaternion.LookRotation((lookPoint) - transform.position);
transform.rotation = rotation;
movementSpeed = Vector2.zero;
}
/// <summary>
/// Custom Raycast using NearClipPlanesPoints
/// </summary>
/// <param name="_to"></param>
/// <param name="from"></param>
/// <param name="hitInfo"></param>
/// <param name="distance"></param>
/// <param name="cullingLayer"></param>
/// <returns></returns>
bool CullingRayCast(Vector3 from, ClipPlanePoints _to, out RaycastHit hitInfo, float distance, LayerMask cullingLayer, Color color)
{
bool value = false;
if (Physics.Raycast(from, _to.LowerLeft - from, out hitInfo, distance, cullingLayer))
{
value = true;
cullingDistance = hitInfo.distance;
}
if (Physics.Raycast(from, _to.LowerRight - from, out hitInfo, distance, cullingLayer))
{
value = true;
if (cullingDistance > hitInfo.distance) cullingDistance = hitInfo.distance;
}
if (Physics.Raycast(from, _to.UpperLeft - from, out hitInfo, distance, cullingLayer))
{
value = true;
if (cullingDistance > hitInfo.distance) cullingDistance = hitInfo.distance;
}
if (Physics.Raycast(from, _to.UpperRight - from, out hitInfo, distance, cullingLayer))
{
value = true;
if (cullingDistance > hitInfo.distance) cullingDistance = hitInfo.distance;
}
return hitInfo.collider && value;
}
}
https://assetstore.unity.com/packages/tools/game toolkits/third -人-控制器基本运动-免费- 82048 #描述
所以我能够修复它。在花了一整天的时间之后,我终于意识到墙上的盒子对撞机太小了。无论如何,从现在开始,我可能会寻找一个更简单的答案,而不是仅仅运行脚本。