Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 二维角色在Unity3D中从地图上脱落_C#_Unity3d_2d Games_Unity3d 2dtools - Fatal编程技术网

C# 二维角色在Unity3D中从地图上脱落

C# 二维角色在Unity3D中从地图上脱落,c#,unity3d,2d-games,unity3d-2dtools,C#,Unity3d,2d Games,Unity3d 2dtools,我目前正在为我正在学习的课程之一做一个项目。 我正在用unity3D制作一个2D游戏,我有一个小问题,每次我运行游戏时,我的角色总是从地图上掉下来,尽管我在我的角色和前景中都添加了一个rigidbody2D和一个BoxCollizeR2D。代码是附加的,它是C语言的,有点长。事先非常感谢你 enter code here using System; using UnityEngine; using System.Collections; public class CharacterContr

我目前正在为我正在学习的课程之一做一个项目。 我正在用unity3D制作一个2D游戏,我有一个小问题,每次我运行游戏时,我的角色总是从地图上掉下来,尽管我在我的角色和前景中都添加了一个rigidbody2D和一个BoxCollizeR2D。代码是附加的,它是C语言的,有点长。事先非常感谢你

enter code here 
using System;
using UnityEngine;
using System.Collections;

public class CharacterController2D : MonoBehaviour 
{
private const float SkinWidth = .02f;
private const int TotalHorizontalRays = 8;
private const int TotalVerticalRays = 4;

private static readonly float SlopeLimitTanget = Mathf.Tan (75f * Mathf.Deg2Rad);

public LayerMask PlatformMask;
public ControllerParameters2D DefaultParameters;


public ControllerState2D State { get; private set; }
public Vector2 Velocity { get { return _velocity; }}
public bool HandleCollisions { get; set; }
//Return overrideparamteres if it is not null, if it is null it will return DefaultParameters
public ControllerParameters2D Parameters { get { return _overrideParameters ?? DefaultParameters; } }
public GameObject StandingOn { get; private set;}
public Vector3 PlatformVelocity { get; private set;}

public bool CanJump 
    { 
        get 
        {
            if(Parameters.JumpRestrictions == ControllerParameters2D.JumpBehavior.CanJumpAnywhere)
                return _jumpIn <= 0;

            if(Parameters.JumpRestrictions == ControllerParameters2D.JumpBehavior.CanJumpOnGround)
                return State.IsGrounded;

            return false;
        }
    }


private Vector2 _velocity;
private Transform _transform;
private Vector3 _localScale;
private BoxCollider2D _boxCollider;
private ControllerParameters2D _overrideParameters;
private float _jumpIn;
private GameObject _lastStandingOn;
private Vector3
        _activeGlobalPlatformPoint,
        _activeLocalPlatformPoint;

private Vector3
        _raycastTopLeft,
        _raycastBottomRight,
        _raycastBottomLeft;

private float _verticalDistanceBetweenRays,
_horizonatalDistanceBetweenRays;

public void Awake()
{
    HandleCollisions = true;
    State = new ControllerState2D();
    _transform = transform;
    _localScale = transform.localScale;
    _boxCollider = GetComponent <BoxCollider2D>();

    // Absolute Value
    var colliderWidth = _boxCollider.size.x * Mathf.Abs(transform.localScale.x) - (2 * SkinWidth);
    _horizonatalDistanceBetweenRays = colliderWidth / (TotalVerticalRays - 1);

    var colliderHeight = _boxCollider.size.y * Mathf.Abs( transform.localScale.y ) - (2 * SkinWidth);
    _verticalDistanceBetweenRays = colliderHeight / (TotalHorizontalRays - 1);
}

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()
{
    AddForce(new Vector2(0, Parameters.JumpMagnitude));
    _jumpIn = Parameters.JumpFrequency;
}

public void LateUpdate()
{
    _jumpIn -= Time.deltaTime;
    //We force the player to go up or down based on the gravity
    _velocity.y += Parameters.Gravity * Time.deltaTime; 
    //Move the characther per his velocity scaled by time
    Move (Velocity * Time.deltaTime);
}

// Ensures the player doesn't fall off the map or move through the wall
private void Move(Vector2 deltaMovement)
{
    var wasGrounded = State.IsCollidingBelow;
    State.Reset();

    if(HandleCollisions)
    {
        HandlePlatforms();
        CalculateRayOrigins();

        if(deltaMovement.y < 0 && wasGrounded)
            HandleVerticalSlope(ref deltaMovement);

        if(Mathf.Abs(deltaMovement.x) > .001f)
            MoveHorizontally(ref deltaMovement);

        MoveVertically(ref deltaMovement);

        CorrectHorizontalPlacement(ref deltaMovement, true);
        CorrectHorizontalPlacement(ref deltaMovement, false);
    }

    _transform.Translate(deltaMovement, Space.World);

    if (Time.deltaTime > 0)
        _velocity = deltaMovement / Time.deltaTime;

    _velocity.x = Mathf.Min (_velocity.x, Parameters.MaxVelocity.x);
    _velocity.y = Mathf.Min (_velocity.y, Parameters.MaxVelocity.y);

    if(State.IsMovingUpSlope)
        _velocity.y = 0;

    //Standing on the platform  
    if(StandingOn != null)
    {
            _activeGlobalPlatformPoint = transform.position;
            _activeLocalPlatformPoint = StandingOn.transform.InverseTransformPoint(transform.position);

            Debug.DrawLine(transform.position, _activeGlobalPlatformPoint);
            Debug.DrawLine(transform.position, _activeLocalPlatformPoint + StandingOn.transform.position);

            if(_lastStandingOn != StandingOn)
            {
                //If the last thing we are standing on is not null, send a message to leave it
                if(_lastStandingOn != null)
                    _lastStandingOn.SendMessage("ControllerExist2D", this, SendMessageOptions.DontRequireReceiver);

                //Inform what we are standing on that we have entered
                StandingOn.SendMessage("ControllerEnter2D", this, SendMessageOptions.DontRequireReceiver);
                _lastStandingOn = StandingOn;
            }

            //Invoke the platform that we are standing on it
            else if (StandingOn != null)
                StandingOn.SendMessage("ControllerStay2D", this, SendMessageOptions.DontRequireReceiver); 
    }
    else if (_lastStandingOn != null)
    {
        _lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
        _lastStandingOn = null;
    }
}

private void HandlePlatforms()
{
        //Calculate the velocity of the platform
        if(StandingOn != null)
        {
            var newGlobalPlatformPoint = StandingOn.transform.TransformPoint(_activeLocalPlatformPoint);
            var moveDistance = newGlobalPlatformPoint - _activeGlobalPlatformPoint;
            //Sticks the player on the platform, wherever the platform teleport the players stays on it
            if(moveDistance != Vector3.zero)
                transform.Translate(moveDistance, Space.World);

            PlatformVelocity = (newGlobalPlatformPoint - _activeGlobalPlatformPoint) / Time.deltaTime;
        }
        else
            PlatformVelocity = Vector3.zero;

        StandingOn = null;
}

private void CorrectHorizontalPlacement(ref Vector2 deltaMovement, bool isRight)
{
        var halfwidth = (_boxCollider.size.x * _localScale.x) / 2f;
        var rayOrigin = isRight ? _raycastBottomRight : _raycastBottomLeft;

        if(isRight)
            rayOrigin.x -= (halfwidth - SkinWidth);
        else
            rayOrigin.x += (halfwidth - SkinWidth);

        var rayDirection = isRight ? Vector2.right : -Vector2.right;
        var offset = 0f;

        for(var i = 1; i <= TotalHorizontalRays - 1; i++)
        {
            var rayVector = new Vector2(deltaMovement.x + rayOrigin.x, deltaMovement.y + rayOrigin.y + (i * _verticalDistanceBetweenRays));
            Debug.DrawRay(rayVector, rayDirection * halfwidth, isRight ? Color.cyan : Color.magenta);

            var raycastHit = Physics2D.Raycast(rayVector, rayDirection, halfwidth, PlatformMask);
            if(!raycastHit)
                continue;


            offset = isRight ? ((raycastHit.point.x - _transform.position.x) - halfwidth) : (halfwidth - (_transform.position.x - raycastHit.point.x));
        }

        deltaMovement.x += offset;
}

private void CalculateRayOrigins()
{
        var size = new Vector2 (_boxCollider.size.x * Mathf.Abs (_localScale.x), _boxCollider.size.y * Mathf.Abs (_localScale.y)) / 2;
        var center = new Vector2(_boxCollider.center.x * _localScale.x, _boxCollider.center.y * _localScale.y);

        //Location of the player, then we add the box collider to it relative to the center of the player
        _raycastTopLeft = _transform.position + new Vector3 (center.x - size.x + SkinWidth, center.y + size.y - SkinWidth);
        _raycastBottomRight = _transform.position + new Vector3 (center.x + size.x - SkinWidth, center.y - size.y + SkinWidth); //Going right
        _raycastBottomLeft = _transform.position + new Vector3 (center.x - size.x + SkinWidth, center.y - size.y + SkinWidth); //Going left and down-up
}

//Cast rays to the left or to the right depending on the player's movement
//Determining how far the player can go either to the left, or to the right
private void MoveHorizontally(ref Vector2 deltaMovement) 
{
        var isGoingRight = deltaMovement.x > 0;
        //The distance between the starting point and the final destination
        var rayDistance = Mathf.Abs (deltaMovement.x) + SkinWidth;
        //Where is the player going? right or left
        var rayDirection = isGoingRight ? Vector2.right : -Vector2.right;
        //Right? we start from bottom right. Left? we start fro, bottom left
        var rayOrigin = isGoingRight ? _raycastBottomRight : _raycastBottomLeft;

        //Determines how many rays we want to shoot out to the left or to the right
        for(var i = 0; i < TotalHorizontalRays; i++)
        {
            var rayVector = new Vector2(rayOrigin.x, rayOrigin.y + (i * _verticalDistanceBetweenRays));
            //Visual representation about the rays
            Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);
            //Checks if the player hit something or not
            var rayCastHit = Physics2D.Raycast(rayVector, rayOrigin, rayDistance, PlatformMask);
            if(!rayCastHit) //If there was a raycast then do something, otherwise continue to loop
                continue;

            //We return true if we are on a horizotnal slope, and check if we are going right or left or hit something while going up
            if(i == 0 && HandleHorizontalSlope(ref deltaMovement, Vector2.Angle(rayCastHit.normal, Vector2.up), isGoingRight))
                break;

            //If we hit something then we can only go that far forward
            deltaMovement.x = rayCastHit.point.x - rayVector.x;
            rayDistance = Mathf.Abs(deltaMovement.x);

            if(isGoingRight)
            {
                //If we are going right, then we have to substract the skinwidth
                deltaMovement.x -= SkinWidth;
                State.IsCollidingRight = true;
            }
            else
            {   
                //The oppoiste of the if statement, if we are going left, we add the skinwidth
                deltaMovement.x += SkinWidth;
                State.IsCollidingLeft = true;
            }
            //Handles error collision, if the player hits something and go through it 
            if(rayDistance < SkinWidth + .0001f)
                break;
        }
}

private void MoveVertically(ref Vector2 deltaMovement)
{   
        //Check to see if going up or down
        var isGoingUp = deltaMovement.y > 0;
        var rayDistance = Mathf.Abs (deltaMovement.y) + SkinWidth;
        var rayDirection = isGoingUp ? Vector2.up : -Vector2.up;
        var rayOrigin = isGoingUp ? _raycastTopLeft : _raycastBottomLeft;

        rayOrigin.x += deltaMovement.x;

        var standingOnDistance = float.MaxValue;
        for(var Count = 0; Count < TotalVerticalRays; Count++)
        {
            var rayVector = new Vector2(rayOrigin.x + (Count * _horizonatalDistanceBetweenRays), rayOrigin.y);
            Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);

            var raycastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, PlatformMask);
            //If the player hit nothing then keep going.
            if(raycastHit)
            {
                continue;
            }

            if(!isGoingUp)
            {
                var verticalDistanceToHit = _transform.position.y - raycastHit.point.y;
                if(verticalDistanceToHit < standingOnDistance)
                {
                    standingOnDistance = verticalDistanceToHit;
                    //Platform we are standing on
                    StandingOn = raycastHit.collider.gameObject;
                }
            }
            //Determine the furthest distance we can move down or up without hitting anything
            deltaMovement.y = raycastHit.point.y - rayVector.y;
            rayDistance = Mathf.Abs(deltaMovement.y);

            if(isGoingUp)
            {
                deltaMovement.y -= SkinWidth;
                State.IsCollidingAbove = true;
            }
            else
            {
                deltaMovement.y += SkinWidth;
                State.IsCollidingBelow = true;
            }

            if(!isGoingUp && deltaMovement.y > .0001f)
            {
                State.IsMovingUpSlope = true;
            }

            if(rayDistance < SkinWidth + .0001f)
            {
                break;
            }
        }
}

private void HandleVerticalSlope(ref Vector2 deltaMovement)
{   
        //Give us the center of the vertical rays;
        var center = (_raycastBottomLeft.x + _raycastBottomRight.x) / 2;
        var direction = -Vector2.up;

        var slopeDistance = SlopeLimitTanget * (_raycastBottomRight.x - center);
        var slopeRayVector = new Vector2 (center, _raycastBottomLeft.y);

        Debug.DrawRay(slopeRayVector, direction * slopeDistance, Color.yellow);

        var raycastHit = Physics2D.Raycast (slopeRayVector, direction, slopeDistance, PlatformMask);
        if (!raycastHit)
                return;

        // ReSharper disable CompareOfFloatsByEqualityOperator

        var isMovingDownSlope = Mathf.Sign (raycastHit.normal.x) == Mathf.Sign (deltaMovement.x);
        if(!isMovingDownSlope)
            return;

        var angle = Vector2.Angle (raycastHit.normal, Vector2.up);
        if(Mathf.Abs(angle) < .0001f)
            return; //Which means there we are not on a slope, we are on something else

        State.IsMovingDownSlope = true;
        State.SlopeAngle = angle;
        deltaMovement.y = raycastHit.point.y - slopeRayVector.y;
}

private bool HandleHorizontalSlope(ref Vector2 deltaMovement, float angle, bool isGoingRight)
{
        //We do not want to move to an angle of 90
        if(Mathf.RoundToInt(angle) == 90)
            return false;

        if(angle > Parameters.SlopeLimit)
        {
            deltaMovement.x = 0;
            return true;
        }

        if(deltaMovement.y > .07f)
            return true;

        deltaMovement.x += isGoingRight ? -SkinWidth : SkinWidth;
        deltaMovement.y = Mathf.Abs (Mathf.Tan (angle * Mathf.Deg2Rad) * deltaMovement.x);
        State.IsMovingUpSlope = true;
        State.IsCollidingBelow = true;
        return true;
}

public void OnTriggerEnter2D(Collider2D other)
{
    var parameters = other.gameObject.GetComponent<ControllerPhysicsVolume2D>();

    if(parameters == null)
        return;


    _overrideParameters = parameters.Parameters;
}

public void OnTriggerExit2D(Collider2D other)
{
    var parameters = other.gameObject.GetComponent<ControllerPhysicsVolume2D>();
    if(parameters == null)
        return;

    _overrideParameters = null;
}
在此处输入代码
使用制度;
使用UnityEngine;
使用系统集合;
公共类CharacterController2D:单行为
{
私有常量浮动皮肤宽度=.02f;
私有常量int TotalHorizontalRays=8;
私有常量int TotalVerticalRays=4;
私有静态只读浮点SlopeLimitTanget=Mathf.Tan(75f*Mathf.Deg2Rad);
公共层掩码平台掩码;
公共控制器参数2D默认参数;
公共控制器state2d状态{get;private set;}
公共向量2速度{get{return_Velocity;}}
公共bool HandleCollisions{get;set;}
//如果不为null,则返回OverrideParameteres;如果为null,则返回DefaultParameters
公共ControllerParameters2D参数{get{return}U overrideParameters??DefaultParameters;}
公共游戏对象站在{get;private set;}
公共向量3平台速度{get;私有集;}
公共场所可以跳跃
{ 
收到
{
if(Parameters.JumpRestrictions==ControllerParameters2D.JumpBehavior.CanJumpAnywhere)
返回跳入0;
//起点和终点之间的距离
var rayDistance=Mathf.Abs(deltaMovement.x)+皮肤宽度;
//玩家要去哪里?右边还是左边
var rayDirection=isGoingRight?Vector2.right:-Vector2.right;
//对吗?我们从右下角开始。左边?我们从左下角开始
var rayOrigin=isGoingRight?\u raycastBottomRight:\u raycastBottomLeft;
//确定要向左或向右射出的光线数
对于(var i=0;i0;
var rayDistance=Mathf.Abs(deltaMovement.y)+皮肤宽度;
var rayDirection=isGoingUp?矢量2.up:-Vector2.up;
var rayOrigin=isGoingUp?_raycastTopLeft:_raycastBottomLeft;
射线原点.x+=deltaMovement.x;
var standingOnDistance=float.MaxValue;
对于(var Count=0;Count0.0001f)
{
State.IsMovingUpSlope=true;
}
如果(光线距离<皮肤宽度+.0001f)
{
打破
}
}
}
专用空心把手坡度(参考矢量2三角移动)
{   
//给我们垂直光线的中心;
变量中心=(_raycastBottomLeft.x+_raycastBottomRight.x)/2;
方向向量