[Chip]Unity开发笔记--类东方Project游戏--Player相关

本文详细介绍了如何在东方Project风格的弹幕射击游戏中,使用Unity的InputSystem配置玩家移动、速度切换、子弹射击、符卡释放、擦弹效果以及角色死亡重生机制。通过PlayerManager单例模式管理玩家行为并实现不同速度模式和碰撞检测。
摘要由CSDN通过智能技术生成

0.按键配置相关

1.使用Input System配置,初始化相关将不作介绍,参考如下

Input System实现移动

2.配置如图

1.设计思路

1.通过PlayerManager控制Player的所有行为,将Player做成预制件PlayerPrefab方便死亡后对Player进行重新生成。

2.作为单例模式使用

private static PlayerController instance;
public static PlayerController Instance { get { return instance; } }
private void Awake()
    {
        instance = this;
    }

2.速度切换

1.生成一个Sphere作为Player的子物体,设置它的Scale到比Player稍小,作为实际中弹的判定点,在Sphere Collider中同样勾选Is Trigger。

2.PlayerManager添加代码如下

AllActions actions;
Vector2 inputVec;
bool isLowSpeed;
Rigidbody rb;
float speed;
public float lowSpeed;
public float highSpeed;
GameObject hitBox;
private void Start()
    {
        rb = player.GetComponent<Rigidbody>();
        actions.Player.LowSpeed.performed += LowMove;
        //注册事件,长按Shift键时将速度设置为低速模式
        actions.Player.LowSpeed.canceled += LowMoveOver;
        //注册事件,松开Shift键时将速度恢复为高速模式
    }
private void FixedUpdate()
    {
        Move();
    }
private void Move()
    {
        inputVec = actions.Player.Move.ReadValue<Vector2>();
        moveVec = player.transform.right * inputVec.x + player.transform.forward * inputVec.y;
        //获取移动方向
        rb.velocity = moveVec.normalized * speed;
        //移动
    }
private void LowMove(InputAction.CallbackContext obj)
    {
        isLowSpeed = true;
        speed = lowSpeed;
        hitBox.GetComponent<Renderer>().enabled = true;
        //低速模式显示判定点
    }
private void LowMoveOver(InputAction.CallbackContext obj)
    {
        isLowSpeed = false;
        speed = highSpeed;
        hitBox.GetComponent<Renderer>().enabled = false;
        //高速模式不显示判定点
    }

3.子弹射击与符卡释放

1.生成一个空物体命名为ShootPos作为Player的子物体,将其设置为Player的正前方

2.PlayerManager添加代码如下

bool isShoot;
public Transform shootPos;
GameObject bulletPrefab;
public float shootCD;
float shootTimer;    
bool isBomb;
GameObject bombPrefab;
private void Start()
    {
        bulletPrefab = Resources.Load<GameObject>("Prefab/Bullet");
        bombPrefab = Resources.Load<GameObject>("Prefab/Bomb");
        actions.Player.Shoot.started += ShootStart;
        //注册事件,按下Z键时开始射击
        actions.Player.Shoot.canceled += ShootOver;
        //注册事件,松开Z键时停止射击
        actions.Player.Bomb.started += BombStart;
        //注册事件,按下X键发射符卡
    }
private void FixedUpdate()
    {
        Shoot();
    }
private void Shoot()
    {
        shootTimer += Time.deltaTime;
        if (shootTimer > shootCD)
        //设置子弹射击间隔
        {
            if (isShoot)
            {
                shootTimer = 0;
                Instantiate(bulletPrefab, shootPos.transform.position, Quaternion.identity);
            }
        }
    }
private void ShootStart(InputAction.CallbackContext obj)
    {
        isShoot = true;
    }
private void ShootOver(InputAction.CallbackContext obj)
    {
        isShoot = false;
    }
private void BombStart(InputAction.CallbackContext obj)
    {
        isBomb = true;
        StartCoroutine(Bomb());
    }
public IEnumerator Bomb()
    {
        Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
        yield return new WaitForSeconds(1);
        Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
        yield return new WaitForSeconds(0.5f);
        Instantiate(bombPrefab, new Vector3(10, 0, -50), Quaternion.identity);
        //克隆三次符卡预制件,实现全屏消弹
        isBomb = false;
    }

 3.符卡身上的脚本

Rigidbody rb;
private void Start()
    {
        rb= GetComponent<Rigidbody>();
        Destroy(gameObject, 4f);
    }
private void Update()
    {
        rb.velocity = Vector3.forward*30;
    }
private void OnTriggerStay(Collider other)
    {
        if (other.tag == "Bullet")
        {
            Destroy(other.gameObject);
        }
    }

4.擦弹实现

1.生成一个空物体命名为Graze作为Player的子物体,为其添加Sphere Collider,勾选Is Trigger,更改它的Radius比Player稍大,这里设置为3。

2.Graze添加代码如下

int graze;
private void OnTriggerExit(Collider other)
//此处使用OnTriggerExit是为了防止Player中弹也增加擦弹次数
    {
        if (other.tag == "Bullet")
        {
            graze+=1;
        }
    }

5.死亡相关

private void FixedUpdate()
    {
        deadTimer -= Time.deltaTime;
        //计算无敌时间
        if (deadTimer <= 0)
        {
            isInvincible = false;
        }
    }
public void PlayerDead()
//该函数在子弹脚本里调用
    {
        if (isInvincible == false)
        {
            if (isDead == false)
            {
                Destroy(player);
                isDead = true;
                isInvincible = true;
                deadTimer = invincibleTime;
                player = Instantiate(playerPrefab, new Vector3(10, 3, -50), Quaternion.identity);
                InitPlayer();
            }
        }
    }
private void PlayerRebirth(Transform player, Vector3 target, float duration)
    {
        player.DOMove(target, duration).OnComplete(PlayerRebirthOver);
        //使用DoTween插件实现Player重生动画
    }
private void PlayerRebirthOver()
    {
        isDead = false;
    }

6.完整项目视频预览

[Demo演示]类东方Project弹幕射击小游戏

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值