我一直在尝试为2D游戏构建一个光线投射控制器,并且已经按照一些教程系列来帮助我更好地理解这是如何完成的。到目前为止,一切进展顺利,我实际上已经完成了关于这个主题的几个教程,没有问题。
然而,在使用这个当前字符控制器时,即使没有编译器错误,我也会在播放时遇到大量错误。我从未见过这个错误,也无法在网上找到有关如何修复它的解决方案。基本上我的角色在游戏中消失了(我假设它被无限移动到左边)。
我得到两个错误:“transform.position assign attempt无效。输入位置是{-infinity,0,0},”和“无效的世界AABB。对象太大或太远离原点。”< / p>
错误发生在第90行:
public void LateUpdate()
{
Move(Velocity * Time.deltaTime);
}
和126:
characterTransform.Translate(deltaMovement, Space.World);
我尝试了很多不同的东西,包括改变角色的比例,将Vector2s改为Vector3s,删除Space.World,直接调用transform.Translate(而不是使用我的characterTransform)。似乎没有什么工作,并且由于某种原因,我的相机有时也会给我一个错误,虽然很难再现。如果我删除任何一行代码,我都没有错误,但显然我的角色无法移动。
错误的屏幕截图:https://imgur.com/a/24KIN
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Handles the character movement with raycasts
/// </summary>
public class CharacterController2D : MonoBehaviour {
//Defines the number of rays
private const int totalHorizontalRays = 8;
private const int totalVeritcalRays = 4;
private RaycastOrigins raycastOrigins; //References the RayCastOrigins struct
private const float skinWidth = .02f; //Defines the skin width of the rays, which places the origin point of the rays slightly inside the character's box collider
private static readonly float slopeLimitTanget = Mathf.Tan(75f * Mathf.Deg2Rad);
public LayerMask platformMask; //Defines the layermask that will be used to determine how different layers interact with the character
public ControllerParameters2D defaultParameters; //References the ControllerParameters2D class
public ControllerState2D State { get; private set; } //References the ControllerState2D class
public ControllerParameters2D Parameters { get { return overrideParameters ?? defaultParameters; } } //Returns updated parameters, or default parameters if overrideParameters is null
public Vector2 Velocity { get { return velocity; } } //Defines the character's velocity
public bool CanJump { get { return false; } } //Defines whether or not the character can jump
public bool HandleCollisions { get; set; } //Defines whether or not the character needs to handle collisions (because it is colliding with something)
private Vector2 velocity; //The field for the Velocity property
private BoxCollider2D boxCollider; //References the box collider on the character
private ControllerParameters2D overrideParameters; //References the updated parameters (that is, the updated parameters, not the default ones)
private Transform characterTransform; //References the character's transform
private Vector3 localScale; //References the character's scale
//The distance between raycasts
private float horizontalDistanceBetweenRays;
private float verticalDistanceBetweenRays;
private struct RaycastOrigins //Stores the value types that define where the raycasts are created on the box collider
{
public Vector2 topLeft, topRight; //Creates variables to define the upper position of the raycasts
public Vector2 bottomLeft, bottomRight; //Creates variables to define the lower position of the raycasts
}
public void Awake()
{
State = new ControllerState2D(); //Accesses the ControllerState2D script
boxCollider = GetComponent<BoxCollider2D>(); //Accesses the character's box collider
characterTransform = transform; //Accesses the character's transform
localScale = transform.localScale; //Accesses the character's scale
//Gets the ray spacing
horizontalDistanceBetweenRays = CalculateHorizontalRaySpacing();
verticalDistanceBetweenRays = CalculateVerticalRaySpacing();
}
public void Start()
{
}
public void AddForce(Vector2 force)
{
velocity += force;
}
public void SetForce(Vector2 force)
{
velocity = force;
}
public void SetHorizontalForce(float x)
{
velocity.x = x;
}
public void SetVerticalForce(float y)
{
velocity.y = y;
}
public void Jump()
{
}
public void LateUpdate()
{
Move(Velocity * Time.deltaTime); //Moves the character per its velocity, scaled by time
}
public void OnTriggerEnter2D(Collider2D other)
{
}
public void OnTriggerExit2D(Collider2D other)
{
}
private void Move(Vector2 deltaMovement)
{
var wasGrounded = State.IsCollidingBelow; //Keeps track of whether or not the character is grounded
State.Reset(); //Resets the state
if (HandleCollisions) //If the character should handle collisions
{
HandlePlatforms();
CalculateRaycastOrigins();
if (deltaMovement.y < 0 && wasGrounded) //If the character is moving down, and was previously grounded...
{
ClimbDownSlope(ref deltaMovement);
}
if (Mathf.Abs(deltaMovement.x) > .001f) //If the character is moving left or right...
{
MoveHorizontally(ref deltaMovement);
}
MoveVertically(ref deltaMovement); //Calls the MoveVertically method always, since the character always has the force of gravity enacted on it
}
characterTransform.Translate(deltaMovement, Space.World); //Moves the character after all potential movement scenarios have been accounted for
if (Time.deltaTime > 0)
{
velocity = deltaMovement / Time.deltaTime; //Sets the current velocity equal to the change in movement
}
//Clamps the velocity to the maximum x and y velocity defined in Parameters
velocity.x = Mathf.Min(velocity.x, Parameters.maxVelocity.x);
velocity.y = Mathf.Min(velocity.y, Parameters.maxVelocity.y);
if (State.IsMovingUpSlope) //If the character is moving up a slope...
{
velocity.y = 0;
}
}
private void MoveHorizontally(ref Vector2 deltaMovement)
{
var isGoingRight = deltaMovement.x > 0; //Defines if the character is going right
var rayDistance = Mathf.Abs(deltaMovement.x) + skinWidth; //Defines the distance of the raycasts
var rayDirection = isGoingRight ? Vector2.right : -Vector2.right; //Defines in which direction the rays will shoot, depdending on character direction
var rayOrigin = isGoingRight ? raycastOrigins.bottomRight : raycastOrigins.bottomLeft; //Defines the current ray origin
for (var i = 0; i < totalHorizontalRays; i++) //Loops through each of the 8 horizontal rays
{
var rayVector = new Vector2(rayOrigin.x, rayOrigin.y + (i * verticalDistanceBetweenRays)); //Builds the rays (stacking them up with each ray that is added)
Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);
var rayCastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, platformMask); //Actually draws the rays
if (!rayCastHit) //If the raycast hits something... (rayCastHit is true)
{
continue;
}
if (i == 0 && ClimbUpSlope(ref deltaMovement, Vector2.Angle(rayCastHit.normal, Vector2.up), isGoingRight)) //If the character is now climbing a slope...
{
break;
}
deltaMovement.x = rayCastHit.point.x - rayVector.x; //Clamps horizontal movement based on ray collision
rayDistance = Mathf.Abs(deltaMovement.x); //Clamps the ray distance based on how far the character is allowed to move (i.e. ensures the rays end at walls)
if (isGoingRight) //If the character is going right...
{
deltaMovement.x -= skinWidth; //Ensures that the character moves with the correct value (otherwise would be able to move slightly more based on skinWidth value)
State.IsCollidingRight = true;
}
else //If the character is going left...
{
deltaMovement.x += skinWidth;
State.IsCollidingLeft = true;
}
if (rayDistance < skinWidth + .0001f) //If a collision gets bugged for some reason...
{
break;
}
}
}
private void MoveVertically(ref Vector2 deltaMovement)
{
}
private void ClimbDownSlope(ref Vector2 deltaMovement)
{
}
private bool ClimbUpSlope(ref Vector2 deltaMovement, float angle, bool isGoingRight)
{
return false;
}
private void HandlePlatforms()
{
}
private float CalculateHorizontalRaySpacing()
{
Bounds bounds = boxCollider.bounds; //Sets the 'bounds' variable equal to the bounds of the box collider on the game object
bounds.Expand(skinWidth * -2); //Enforces the skinWidth variable
return bounds.size.y / (totalHorizontalRays - 1); //Ensures that all rays are spaced evenly on the sides of the box collider
}
private float CalculateVerticalRaySpacing()
{
Bounds bounds = boxCollider.bounds; //Sets the 'bounds' variable equal to the bounds of the box collider on the game object
bounds.Expand(skinWidth * -2); //Enforces the skinWidth variable
return bounds.size.x / (totalVeritcalRays - 1); //Ensures that all rays are spaced evenly on the bottom and top of the box collider
}
private void CalculateRaycastOrigins()
{
Bounds bounds = boxCollider.bounds; //Sets the 'bounds' variable equal to the bounds of the box collider on the game object
bounds.Expand(skinWidth * -2); //Enforces the skinWidth variable
//Creates the starting positions of the raycasts
raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
}
}
答案 0 :(得分:1)
在做了一些研究后,似乎这是一个有时会发生的错误。
我不确定为什么我不早点尝试这个,但重新安装Unity修复了所有问题......