【Unity脚本】游戏开发常用功能——以平台动作游戏为例解决“瞬移穿墙”问题

核心代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Author:圈毛君
/// MoveController:2019/10/18 20:50
/// </summary>
public class PlayerController : MonoBehaviour
{
    public float exStepDistance = 3.0f;    // 瞬步距离(速度)

    private bool exStepEnabled = true;     // 能否使用瞬步

    public void MoveController()
    {
        if (Input.GetKey(KeyCode.A))
        {
            if (Input.GetKeyDown(KeyCode.LeftShift) && exStepEnabled)
            {
                float tempStepDistance = exStepDistance;        // 临时瞬步距离
                Vector3 temp = transform.position;
                RaycastHit2D hit = Physics2D.Raycast(new Vector2(temp.x - 0.6f, temp.y), new Vector2(-1, 0), exStepDistance);   // 使用Raycast解决穿墙问题
                if (hit)
                {// 仅通过Raycast判断还不能解决贴墙穿越的问题,需要在碰撞事件中进一步处理
                    tempStepDistance = hit.distance;            // 重新赋值瞬步距离
                }
                transform.position = new Vector3(-tempStepDistance + temp.x, temp.y, temp.z);    // 虽然可以瞬步,但要解决穿墙的BUG
            }
        }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.name != "Floor")    // 某些物体的碰撞不可计算在内
        {
            exStepEnabled = false;
        }
    }

    private void OnCollisionStay2D(Collision2D collision)
    {
        if (collision.gameObject.name != "Floor")
        {
            exStepEnabled = false;
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.name != "Floor")
        {
            exStepEnabled = true;
        }
    }
}

完整移动代码(包括A/D步行、双击A/D跑步、A/D+Shift瞬移)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Author:圈毛君
/// MoveController:2019/10/18 20:50
/// </summary>
public class PlayerController : MonoBehaviour
{
    public float walkSpeed = 3.0f;         // 步行速度
    public float runSpeed = 5.0f;          // 跑步速度
    public float pressInterval = 0.5f;     // 双击按键的有效时间间隔
    public float exStepDistance = 3.0f;    // 瞬步距离(速度)

    private Rigidbody2D rgb;
    private SpriteRenderer sr;
    private Color originColor;
    private float pressATime;              // 按下A键时间
    private float pressDTime;
    private float releaseATime = .0f;      // 松开A键时间
    private float releaseDTime = .0f;
    private bool exStepEnabled = true;     // 能否使用瞬步

    private void Awake()
    {
        rgb = this.GetComponent<Rigidbody2D>();
        sr = this.GetComponent<SpriteRenderer>();
        originColor = sr.color;
    }

    private void Update()
    {
        MoveController();                           // 移动控制
    }

    public void MoveController()
    {
        if (Input.GetKeyUp(KeyCode.A))              // 不能||D,否则快速AD也算双击有效时间
        {
            releaseATime = Time.time;
            sr.color = originColor;
            rgb.velocity = new Vector2(0, 0);       // Stop
        }

        if (Input.GetKeyUp(KeyCode.D))
        {
            releaseDTime = Time.time;
            sr.color = originColor;
            rgb.velocity = new Vector2(0, 0);
        }

        if (Input.GetKey(KeyCode.A))
        {
            if (Input.GetKeyDown(KeyCode.LeftShift) && exStepEnabled)
            {
                float tempStepDistance = exStepDistance;        // 临时瞬步距离
                Vector3 temp = transform.position;
                RaycastHit2D hit = Physics2D.Raycast(new Vector2(temp.x - 0.6f, temp.y), new Vector2(-1, 0), exStepDistance);   // 使用Raycast解决穿墙问题
                if (hit)
                {// 仅通过Raycast判断还不能解决贴墙穿越的问题,需要在碰撞事件中进一步处理
                    tempStepDistance = hit.distance;            // 重新赋值瞬步距离
                }
                transform.position = new Vector3(-tempStepDistance + temp.x, temp.y, temp.z);    // 虽然可以瞬步,但要解决穿墙的BUG
            }
            pressATime = Time.time;
            if(pressATime - releaseATime <= pressInterval)
            {
                rgb.velocity = new Vector2(-runSpeed, 0);       // 跑步
                sr.color = new Color(1, 0, 0);
                releaseATime = Time.time;                       // 跑步状态中要持续更新松键时间
            }
            else
                rgb.velocity = new Vector2(-walkSpeed, 0);      // 步行
        }

        if (Input.GetKey(KeyCode.D))
        {
            if (Input.GetKeyDown(KeyCode.LeftShift) && exStepEnabled)
            {
                float tempStepDistance = exStepDistance;
                Vector3 temp = transform.position;
                RaycastHit2D hit = Physics2D.Raycast(new Vector2(temp.x + 0.6f, temp.y), new Vector2(1, 0), exStepDistance);
                if (hit)
                {
                    tempStepDistance = hit.distance;
                }
                transform.position = new Vector3(tempStepDistance + temp.x, temp.y, temp.z);
            }
            pressDTime = Time.time;
            if (pressDTime - releaseDTime <= pressInterval)
            {
                rgb.velocity = new Vector2(runSpeed, 0);
                sr.color = new Color(1, 0, 0);
                releaseDTime = Time.time;
            }
            else
                rgb.velocity = new Vector2(walkSpeed, 0);
        }
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.name != "Floor")    // 某些物体的碰撞不可计算在内
        {
            exStepEnabled = false;
        }
    }

    private void OnCollisionStay2D(Collision2D collision)
    {
        if (collision.gameObject.name != "Floor")
        {
            exStepEnabled = false;
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.name != "Floor")
        {
            exStepEnabled = true;
        }
    }
}
发布了153 篇原创文章 · 获赞 184 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Ha1f_Awake/article/details/102632711