006_2D Ruby 项目脚本

006_2D Ruby 项目脚本

CogBulletController.cs

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);
    }
}

DamageZone.cs

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);
        }
    }
}

EnemyController.cs

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;
    //粒子系统
    public ParticleSystem smokeEffect;

    //robot是否修复
    bool repaired;

    AudioSource audioSource;

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

    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");
        //特效在生命周期后停止
        smokeEffect.Stop();
        audioSource.Stop();
    }
}

HealthCollectible.cs

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

public class HealthCollectible : MonoBehaviour
{
    public AudioClip collectedClip;
    //音频音量
    public float soundVol = 1.0f;
    //草莓加的血量
    public int amount = 1;
    //碰撞次数
    int collideCount;
    //添加触发器碰撞事件
    private void OnTriggerEnter2D(Collider2D collision)
    {
        collideCount++;
        Debug.Log($"和当前物体发生碰撞的对象是:{collision},当前是第{collideCount}次碰撞!");

        //获取Ruby游戏对象的脚本组件对象
        RubyController rubyController = collision.GetComponent<RubyController>();
        if (rubyController != null)
        {
            Debug.Log($"ruby health is {rubyController.health}");
            if (rubyController.health < rubyController.maxHealth)
            {
                //更改血量
                rubyController.ChangeHealth(amount);
                //销毁当前游戏对象:草莓
                Destroy(gameObject);
                //播放吃草莓的音频
                rubyController.PlaySound(collectedClip, soundVol);
            }
            else
            {
                Debug.Log("当前玩家角色生命是满的,不需要加血");
            }
        }
        else
        {
            Debug.LogError("rubyController游戏组件并未获取到");
        }

    }
}

NonPlayerCharacter.cs

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

public class NonPlayerCharacter : MonoBehaviour {
    //对话显示时长
    public float displayTime = 4.0f;
    //对话框游戏对象
    public GameObject dialogBox;
    //文本框计时器
    float displayTimer;
    //TMP控件
    public GameObject tmpGameObject;
    //游戏组件类
    TextMeshProUGUI tmpTextBox;
    //当前页数
    int currentPage = 1;
    //总页数
    int totalPages;

    // Start is called before the first frame update
    void Start() {
        //游戏开始不显示对话框
        dialogBox.SetActive(false);
        //计时器开始不可用
        displayTimer = -1.0f;

        tmpTextBox = tmpGameObject.GetComponent<TextMeshProUGUI>();
    }

    // Update is called once per frame
    void Update() {
        if (displayTimer >= 0.0f) {
            //循环翻页
            if (Input.GetKeyDown(KeyCode.Space)) {
                if (currentPage < totalPages) {
                    currentPage++;
                } else {
                    currentPage = 1;
                }
                tmpTextBox.pageToDisplay = currentPage;
            }
            displayTimer -= Time.deltaTime;
        } else {
            dialogBox.SetActive(false);
        }
    }

    public void DisplayDialog() {
        //获取对话框总页数
        totalPages = tmpTextBox.textInfo.pageCount;
        //重置对话框显示时间
        displayTimer = displayTime;
        dialogBox.SetActive(true);
    }
}

RubyController.cs

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 {
    //声明音频源对象,用来后期进行音频播放控制
    AudioSource audioSource;
    //子弹预制件对象
    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>();

        audioSource = GetComponent<AudioSource>();
    }

    // 每帧调用一次 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();
        }

        if(Input.GetKeyDown(KeyCode.E)) {
            //创建射线投射碰撞对象,接收射线投射碰撞信息
            //参数1:射线投射的位置
            //参数2:投射方向
            //参数3:投射距离
            //参数4:射线生效的层
            RaycastHit2D hit = Physics2D.Raycast(rigidbody2D.position + Vector2.up * 0.2f, move, 1.5f, LayerMask.GetMask("NPC"));
            if (hit.collider != null) {
                Debug.Log($"射线投射碰撞到的对象是:{hit.collider.gameObject}");
                NonPlayerCharacter npc = hit.collider.GetComponent<NonPlayerCharacter>();
                if (npc != null) {
                    npc.DisplayDialog();
                }
            }
        }
    }

    //固定时间间隔执行的更新方法
    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);

        UIHealthBar.instance.SetValue(currentHealth/(float)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");
    }

    //播放音频
    public void PlaySound(AudioClip audioClip, float soundVol) {
        audioSource.PlayOneShot(audioClip, soundVol);
    }
}

UIHealthBar.cs

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

public class UIHealthBar : MonoBehaviour {
    //创建公有静态成员,获取当前血条本身
    public static UIHealthBar instance { get; private set; }
    public Image mask;
    float originalSize;

    void Awake() {
        instance = this;
    }

    // Start is called before the first frame update
    void Start() {
        //获取遮罩层图形的初始宽度
        originalSize = mask.rectTransform.rect.width;
    }

    // Update is called once per frame
    void Update() {

    }

    public void SetValue(float value) {
        //设置mask遮罩层的宽度
        mask.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, originalSize*value);
    }

}

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