游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统)

这篇具有很好参考价值的文章主要介绍了游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统)

目标:使用 Unity 实现跳墙机制,让玩家在平台游戏中到达更高的位置。

到目前为止,在这个项目中,我已经介绍了如何创建具有双跳功能的物理基础角色控制器。我添加了动态平台、收藏品和事件驱动的电梯。

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎

今天我将回到角色控制器脚本(Player)并添加墙跳功能。这将允许玩家检测墙壁的表面并从一堵墙跳到另一堵墙。
场景设置

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎

我的场景有一个平台和两堵墙,创建了一条向上的路径。到达顶部的唯一方法是在两堵墙之间跳墙。

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎

现在,我将两堵墙标记为“Wall”,作为玩家控制器检测要在哪堵特定墙上执行墙跳跃的一种方式。
游戏输入脚本
再一次,这一切都是通过 Unity 的新输入系统(Input System)完成的。我有一个单独的脚本来处理附加到玩家的游戏输入。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameInput : MonoBehaviour
{
    private ActionMaps _input;
    public event EventHandler OnInteract;
    private void Awake()
    {
        _input = new ActionMaps();
    }

    private void OnEnable()
    {
        _input.Player.Enable();
        _input.Player.Interact.performed += Interact_performed;
    }

    private void Interact_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj)
    {
        OnInteract?.Invoke(this,EventArgs.Empty);
    }

    public Vector2 GetMovementVectorNormalized() 
    {
        Vector2 _direction = _input.Player.Move.ReadValue<Vector2>();
        _direction = _direction.normalized;
        return _direction;
    }

    public bool IsJumping() 
    {
        if (_input.Player.Jump.IsPressed())
            return true;
        else return false;
    }
}
实施跳墙
需要一些变量、方法和 if 语句来使墙跳转到与当前角色控制器一起工作。
玩家控制器脚本
我添加了新的字段变量:
Float wallJumpForce X & Y:这决定了 X 和 Y 方向上墙跳跃的强度。
Bool _canWallJump:检查玩家是否可以跳墙
Vector3 WallJumpNormal:这将存储我们想要跳跃方向的表面法线的 Vector3。
OnControllerColliderHit 方法
接下来,我使用角色控制器的 Collider hit 方法来检测玩家碰撞的对象。我们可以通过使用 hit 变量来获取对象的变换,然后比较对象的标签以找到可跳跃的墙。当玩家与墙壁碰撞时会投射蓝色光线,代表表面法线,该法线将用作墙壁跳跃的方向矢量(vector)。

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎

If 语句:只想当玩家在空中而不接触地面时进行墙跳,并且tag==“Wall”。
private void OnControllerColliderHit(ControllerColliderHit hit)
    {

        if (_controller.isGrounded == false && hit.transform.CompareTag("Wall"))
        {
            Debug.DrawRay(hit.point, hit.normal, Color.blue);
            if (hit.normal.x == 1f || hit.normal.x == -1f) 
            {
                _wallJumpNormal = hit.normal * _wallJumpForceX;
                _canWallJump = true;
            }
        }    
    }

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎Non-Bug Wall Jump

下一个 if 语句检查法线表面的 x 值。我们希望 x 法线为 1f 或 -1f。意味着表面垂直于玩家(flat)。这可以防止玩家意外跳入角落并被发射到太空(如下所示)。

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎由于乘以跳跃力而显示
2.50 force. NormalVector * 2.50f

然后我们采用字段变量 _wallJumpNormal 并让它等于 hit.normal * wallJumpForceX (NormalVector (1.0/-1.0,0,0) * 2.50f) 和 _canWallJump = true。
if (hit.normal.x == 1f || hit.normal.x == -1f) 
            {
                _wallJumpNormal = hit.normal * _wallJumpForceX;
                _canWallJump = true;
            }
        }
运动方式
之后就是调整动作方法的时候了。
每当玩家接触地面墙壁时,跳跃就会被禁用。
if (_groundPlayer == true)
        {
            _canWallJump = false;
            _controller.Move(Vector3.zero);
            _yVelocity = -_gravity;
        }
当玩家在空中时,我们有两个选择:墙跳或二段跳。
Wall Jumping(跳墙):只有在满足条件的情况下,我们才会检查是否允许玩家跳墙。如果我们可以进行墙跳,请关闭双跳功能,将 xVelocity 向量设置为 _wallJumpNormal Vector,并添加 yVelocity。
if ((_canWallJump && _gameInput.IsJumping() && Time.time > _jumpDelay))
            {
                _doubleJump = true;
                _canWallJump = false;
                _xVelocity = _wallJumpNormal;

                if (_yVelocity < 0)
                {
                    _yVelocity = 0;
                    _yVelocity += _wallJumpForceY;
                }
                else
                    _yVelocity += _wallJumpForceY;
            }

游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统),unity3d开发教学,unityc#教程,游戏开发小结,unity,游戏,游戏引擎文章来源地址https://www.toymoban.com/news/detail-790044.html

然后这些值被传递到更新玩家速度和方向的移动方法中的最后一行代码。
Vector3 _movement = new Vector3(_xVelocity.x, _yMaxVelocity, 0);
            _controller.Move(_movement * Time.deltaTime);
总之,这就是我在这个项目中实现跳墙功能的方法。这是通过获取玩家的墙壁表面法线并使用该矢量(vector)将玩家推向下一面墙壁来实现的。
完整的玩家脚本
using UnityEngine;
using UnityEngine.SceneManagement;

public class Player : MonoBehaviour
{
    private GameInput _gameInput;
    private CharacterController _controller;
    
    [SerializeField] private float _speed = 2.0f;
    [SerializeField] private float _jumpStrength = 15.0f;
    [SerializeField]private float _gravity = 1.0f;
    [SerializeField] private bool _groundPlayer;
    
    public int _coinCollected { get; private set; } = 0;
    private int _lives = 3;
    
    private float _yVelocity;
    private  Vector3 _direction;
    private Vector3 _xVelocity;
    
    private bool _doubleJump;
    private float _jumpDelay;
    
    [SerializeField] private float _wallJumpForceX;
    [SerializeField] private float _wallJumpForceY;
    [SerializeField] private bool _canWallJump;
    [SerializeField] private Vector3 _wallJumpNormal;
    private void Awake()
    {
        _gameInput = GetComponent<GameInput>();
        _controller = GetComponent<CharacterController>();
        if (_gameInput == null) Debug.LogError("Missing Game Input");
        if (_controller == null) Debug.LogError("Missing Character Controller");
    }

    private void Start()
    {
        UIManager._instance.UpdateLivesText(_lives);
        UIManager._instance.UpdateCoinText(_coinCollected);
    }

    private void Update()
    {
        Movement();
        ResetSpawn();
        Death();
    }

    private void OnControllerColliderHit(ControllerColliderHit hit)
    {


        if (_controller.isGrounded == false && hit.transform.CompareTag("Wall"))
        {
            Debug.DrawRay(hit.point, hit.normal, Color.blue);
            if (hit.normal.x == 1f || hit.normal.x == -1f) 
            {
                _wallJumpNormal = hit.normal * _wallJumpForceX;
                _canWallJump = true;
            }
        }    
    }


    private void Movement()
    {
        _groundPlayer = _controller.isGrounded;


        if (_groundPlayer == true)
        {
            _canWallJump = false;
            _controller.Move(Vector3.zero);
            _yVelocity = -_gravity;
        }

        if (_groundPlayer == true && _gameInput.IsJumping() && !_canWallJump)
        {
            _yVelocity += _jumpStrength;
            _doubleJump = false;
            _jumpDelay = Time.time + 0.3f;

        }
        else if (_groundPlayer == false)
        {
            if ((_canWallJump && _gameInput.IsJumping() && Time.time > _jumpDelay))
            {
                _doubleJump = true;
                _canWallJump = false;
                _xVelocity = _wallJumpNormal;

                if (_yVelocity < 0)
                {
                    _yVelocity = 0;
                    _yVelocity += _wallJumpForceY;
                }
                else
                    _yVelocity += _wallJumpForceY;
            }

            if ((!_doubleJump && _gameInput.IsJumping() && Time.time > _jumpDelay))
            {
                _doubleJump = true;
              
                if (_yVelocity < 0)
                {
                    _yVelocity = 0;
                    _yVelocity += 6f;
                }
                else
                    _yVelocity += 6f;

            }

            _yVelocity -= _gravity * Time.deltaTime;

        }

        var _yMaxVelocity = Mathf.Clamp(_yVelocity, -20, 100f);
        
        if (_groundPlayer == true)
        {
            _direction = _gameInput.GetMovementVectorNormalized();
            _xVelocity = _direction * _speed;
        }

   
            Vector3 _movement = new Vector3(_xVelocity.x, _yMaxVelocity, 0);
            _controller.Move(_movement * Time.deltaTime);
    }

    private void ResetSpawn() 
    {
        Vector3 _currentPosition = transform.position;
        Vector3 _spawnLocation = new Vector3(0, 1, 0);
        bool uiZeroLivesText = _lives > 0;

        if (_currentPosition.y < -5) 
        {
            transform.position = _spawnLocation;
            _lives--;
            if(uiZeroLivesText)
            UIManager._instance.UpdateLivesText(_lives);
        }
    }


    private void Death() 
    {
        if(_lives < 0) 
        {
            SceneManager.LoadScene(0);
        }
    }

    public void AddCoins() 
    {
        _coinCollected++;
        UIManager._instance.UpdateCoinText(_coinCollected);
    }

}

到了这里,关于游戏开发小结——Unity 2.5D 平台游戏:跳墙(新输入系统)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity实战篇 】| 2.5D游戏是如何做出来的呢,2.5D游戏快速制作教程

    前言 玩过游戏的朋友都知道,市面上最常见的游戏多数分为2D和3D两种。 2D和3D游戏之间的差异大家都知道,一个是类似纸片游戏属于二维层面,另一个则是在3D立体空间中游玩。 其中还夹杂着一个 2.5D游戏 ,本篇文章就来讲一下怎么通过Unity进行2.5D游戏是怎样的以及如何制作

    2024年02月12日
    浏览(54)
  • 【用unity实现100个游戏之9】使用Unity制作类八方旅人、饥荒风格的俯视角2.5D游戏(附工程代码)

    【视频】:https://www.bilibili.com/video/BV1DT4y1A7DJ/ 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入 2.5D游戏 是一种介于二维和三维之间的游戏形式。它通常在二维平面上展示游戏内容,但利用三维技术来实现更加逼真的图像效果。 在2.5D游戏

    2024年02月04日
    浏览(44)
  • 【Unity_Input System】Input System新输入系统(三)——在游戏中更换按键绑定

    Binding只由一个部分组成,一般绑定单个按键或者摇杆 CompositeBinding由两个以上部分组成,一般是用于将多个按键组成虚拟轴 更换按键绑定时,Binding和Composite Binding需要分别处理,对Composite Binding需要循环各个部分进行修改。 可以用InputBinding.isComposite来判断是否是Composite Bind

    2024年02月04日
    浏览(39)
  • Unity游戏开发之游戏动画(Unity动画系统)

    Unity动画系统分为 动画片段 Animation Clip: 动画资源,与模型无关 动画状态机 Animator Controller:帮助我们跟踪当前动画的播放状态,并且根据设置觉得如何切换动画片段 动画组件 Animator Component:玩家角色需要播放动画功能时,需要动画组件,将游戏对象需要的动画状态机(以

    2024年02月13日
    浏览(41)
  • 【Unity游戏开发】动画系统(三)按钮动画

    动画系统是一个比较重要的系统,因为我们做游戏是离不开这个东西的,但是我们又不用自己做动画,而动画系统就是管理美工做的动画,我们加以修饰,使之适配我们的游戏 而按钮动画也是一个点,当然重不重要其实还是你说了算,而按钮动画适配我们的2D和3D游戏 用于

    2024年02月09日
    浏览(40)
  • [游戏开发]Unity红点系统_树实现

    刚好处理到红点系统的问题,就写个文章记录一下。本文的红点系统为一个 树 结构,UI实现需要和红点运行逻辑剥离,防止过度耦合,现在就暂时不提及,后续在讲述。 红点是游戏中一种常见且重要的提醒方式,通常涉及到很多方面信息和界面的显示,如果不做成独立的系

    2024年02月06日
    浏览(28)
  • unity开发知识点小结02

    虚拟轴就是一个数值在-1 1内的轴,这个数轴上重要的数值就是-1,0和1。当使用按键模拟一个完整的虚拟轴时需要用到两个按键,即将按键1设置为负轴按键,按键2设置为正轴按键。在没有按下任何按键的时候,虚拟轴的数值为0;在按下按键1的时候,虚拟轴的数值会从0 -1进行

    2024年02月07日
    浏览(35)
  • Unity SteamVR 开发教程:SteamVR Input 输入系统(2.x 以上版本)

    输入系统是 VR 开发中非常重要的一部分。我们通常需要获取 VR 手柄上某个按键的输入,然后将其作用到应用中,比如按下手柄的 Grip 键进行抓取,就需要在检测到“按下手柄 Grip 键”的输入操作时,执行抓取的行为。 SteamVR 插件是 Valve 提供给 Unity 开发者的用于开发 PCVR (头

    2024年02月08日
    浏览(36)
  • Azure Kinect微软摄像头Unity开发小结

    Azure Kienct是微软的代替Kinect的摄像头,用处其实蛮多的,最近做了这个的一些开发,总结一下。 如果只是当普通摄像头用的话,有集成显卡就行了。如果要用人体跟踪,至少要1050的独显。 微软摄像头代的东西还不少,可以建立点云地图,但是没试过。 下面是官方的SDK。后面

    2024年02月04日
    浏览(41)
  • 【3519DV500】AI算法承载硬件平台_2.5T算力+AI ISP图像处理_超感光视频硬件方案开发

    Hi3519DV500集成了高效的神经网络推理引擎,最高2.5Tops NN算力,支持业界主流的神经网络框架。神经网络支持完整的 API 和工具链,易于客户开发,升级 IVE 算子,支持特征点检测、周界、光流及多种计算机形态学算子;升级 DPU 算法实现双目深度图加速单元,最大分辨率 2048

    2024年02月03日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包