005_添加动画、子弹碰撞、无敌时间

005_添加动画、子弹碰撞、无敌时间

RubyController

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.PlayerLoop;
using UnityEngine.UIElements;
using UnityEngine.WSA;

public class RubyController : MonoBehaviour {
    //子弹预制件对象
    public GameObject cogBulletPrefab;
    //无敌时间
    public float invincibleTime = 2.0f;
    //无敌时间计时器
    public float invincibleTimer;
    //是否无敌的标志
    bool isInvincible;
    //最大生命值
    public int maxHealth = 5;

    //C#中支持面向对象程序设计中的封装概念,对数据成员的保护
    //数据成员变量,默认一般都应该设置为私有,只能通过当前类的方法或属性进行访问
    //属性是公有的,可以通过取值器get、赋值器 set设定对应字段的访问规则,满足规则才能够访问
    public int health {
        get { return currentHealth; }
        //set { currentHealth = value; }
    }
    //当前生命值
    int currentHealth;

    // 将速度暴露出来,使其可调
    public float speed = 4f;

    //声明刚体对象
    Rigidbody2D rigidbody2D;
    //获取用户输入
    public float horizontal = 0f;
    public float vertical = 0f;

    //动画管理组件
    Animator animator;

    Vector2 move;

    // 在第一次帧更新之前调用 Start
    private void Start() {
        //获取当前游戏对象的刚体组件
        rigidbody2D = GetComponent<Rigidbody2D>();
        //游戏开始,玩家满血
        currentHealth = 3;
        Debug.Log($"currentHealth:{currentHealth}");

        move = new Vector2(1, 0);

        animator = GetComponent<Animator>();
    }

    // 每帧调用一次 Update
    void Update() {
        /* 根据按键移动上下左右的位置:每帧移动0.1 */
        //获取水平输入,按向左会获得-1.0f,按向右会获得1.0f
        horizontal = Input.GetAxis("Horizontal");
        //获取垂直输入按向下会获得-1.0f,按向上会获得1.0f
        vertical = Input.GetAxis("Vertical");

        if (!Mathf.Approximately(horizontal, 0f) || !Mathf.Approximately(vertical, 0f)) {
            move = new Vector2(horizontal, vertical);
            move.Normalize();
            animator.SetFloat("Look X", move.x);
            animator.SetFloat("Look Y", move.y);
            animator.SetFloat("Speed", move.magnitude);
        } else {
            animator.SetFloat("Speed", 0);
        }

        //是否处于无敌状态
        if (isInvincible) {
            //无敌计数器减去一帧的时间
            invincibleTimer -= Time.deltaTime;

            if (invincibleTimer < 0) {
                isInvincible = false;
            }
        }

        //按住Shift加快移速
        if(Input.GetKeyDown(KeyCode.LeftShift)) {
            speed = 8f;
        } else if(Input.GetKeyUp(KeyCode.LeftShift)) {
            speed = 4f;
        }

        //按下鼠标左键发射子弹
        if (Input.GetMouseButtonDown(0)) {
            Launch();
        }
    }

    //固定时间间隔执行的更新方法
    private void FixedUpdate() {
        //获取对象当前位置
        Vector2 position = rigidbody2D.position;
        //更改位置,Time.deltaTime 每帧的时间间隔,float 类型
        position.x = position.x + speed * horizontal * Time.deltaTime;
        position.y = position.y + speed * vertical * Time.deltaTime;
        //新位置给游戏对象
        rigidbody2D.position = position;
    }

    //更改生命值的方法
    public void ChangeHealth(int amount) {
        if (amount < 0) {
            animator.SetTrigger("Hit");
            if (isInvincible) {
                return;
            }
            isInvincible = true;
            invincibleTimer = invincibleTime;
        }
        //限制方法,限制当前生命值的赋值范围:0~最大生命值
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
        Debug.Log("当前生命值:" + currentHealth + "/" + maxHealth);


    }

    private void Launch() {
        //创建子弹游戏对象
        GameObject cogBulletObject = Instantiate(cogBulletPrefab, rigidbody2D.position + Vector2.up * 0.5f, Quaternion.identity);
        //获取子弹游戏对象的脚步组件
        CogBulletController cogBullet = cogBulletObject.GetComponent<CogBulletController>();
        //通过脚步对象调用子弹移动的方法
        //params:移动的方向,力
        cogBullet.Launch(move, 600);
        //发射动画
        animator.SetTrigger("Launch");
    }
}

EnemyController

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class EnemyController : MonoBehaviour {
    //每次掉血量
    public int damageNum = -1;
    //敌人移动速度
    public float speed = 3f;
    //声明刚体对象
    Rigidbody2D rigidbody2D;
    //移动方向
    public float horizontal = 0;
    public float vertical = 1;
    //移动时间
    public float moveTime = 3;
    //移动计时器
    float moveTimer;
    //动画管理组件
    Animator animator;

    //robot是否修复
    bool repaired;

    private void Start() {
        rigidbody2D = GetComponent<Rigidbody2D>();
        moveTimer = moveTime;
        animator = GetComponent<Animator>();
    }

    private void Update() {
        //如果robot已修复,就不再移动
        if (repaired) {
            return;
        }
        moveTimer -= Time.deltaTime;
        if (moveTimer < 0) {
            vertical *= -1;
            horizontal *= -1;
            moveTimer = moveTime;
        }
    }

    //固定时间间隔执行的更新方法
    private void FixedUpdate() {
        //如果robot已修复,就不再移动
        if (repaired) {
            return;
        }
        //获取对象当前位置
        Vector2 position = rigidbody2D.position;
        //更改位置,Time.deltaTime 每帧的时间间隔,float 类型
        position.x = position.x + speed * horizontal * Time.deltaTime;
        position.y = position.y + speed * vertical * Time.deltaTime;
        //新位置给游戏对象
        rigidbody2D.position = position;

        animator.SetFloat("Move X", position.x);
        animator.SetFloat("Move Y", position.y);

    }

    //刚体碰撞事件方法
    private void OnCollisionEnter2D(Collision2D collision) {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();
        if (rubyController != null) {
            rubyController.ChangeHealth(damageNum);
        }
    }

    public void Fix() {
        //robot已修复
        repaired = true;
        //让robot不再受碰撞,刚体对象取消物理引擎效果
        rigidbody2D.simulated = false;
        //播放修复后的动画
        animator.SetTrigger("Fixed");
    }
}

CogBulletController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CogBulletController : MonoBehaviour {
    Rigidbody2D rigidbody2D;
    // Start is called before the first frame update
    void Start() {
        
    }

    private void Awake() {
        rigidbody2D = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update() {
        //飞行距离超过100单位后,自动销毁
        if(transform.position.magnitude > 100f) {
            Destroy(gameObject);
        }
    }

    //direction:方向,force:力
    public void Launch(Vector2 direction, float force) {
        //对游戏对象施加一个力,使其移动
        rigidbody2D.AddForce(direction * force);
    }

    private void OnCollisionEnter2D(Collision2D collision) {
        //获取子弹碰撞到的游戏对象脚步组件
        EnemyController enemyController = collision.gameObject.GetComponent<EnemyController>();
        if (enemyController != null) {
            enemyController.Fix();
        }
        //打印子弹碰撞到的游戏对象
        Debug.Log($"齿轮子弹碰撞到了: {collision.gameObject}");
        //销毁子弹
        Destroy(gameObject);
    }
}

DamageeZone

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DamageZone : MonoBehaviour
{
    //每次掉血量
    public int damageNum = -1;

    //刚体在触发器内的每一帧都会调用此函数,而不是在刚体刚进入时仅调用一次。
    private void OnTriggerStay2D(Collider2D collision)
    {
        RubyController rubyController = collision.gameObject.GetComponent<RubyController>();

        if(rubyController != null )
        {
            rubyController.ChangeHealth(damageNum);
        }
    }
}

posted @   爱吃冰激凌的黄某某  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示