2D Rubys冒险记游戏实现脚本合集

这是一个2D游戏的脚本合集,涵盖了从玩家控制器(PlayerController.cs)、敌人控制器(EnemyController.cs)到场景管理(SceneController.cs)和音频管理(AudioManager.cs)等多个关键组件。还包括了物品系统、子弹行为、NPC管理以及UI交互等,为Ruby的冒险游戏提供了全面的代码支持。
摘要由CSDN通过智能技术生成

PlayerController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
/// <summary>
/// 控制角色移动、生命、动画等
/// </summary>
public class PlayerController : MonoBehaviour
{
   
    public float speed = 5f;//移动速度

    private int maxHealth = 5;//最大生命值

    private int currentHealth;//当前的生命值
    //========玩家死亡结束游戏==============================
    //游戏结束提示
    //public GameObject GameOver;
    //指定为主角并销毁
    public GameObject GameOverPlayer;

    public int MyMaxHealth {
    get {
    return maxHealth; } }//在这里定义一个公共属性以便Collectible.cs可以访问生命属性

    public int MyCurrentHealth {
    get {
    return currentHealth; } }//在这里定义一个公共属性以便Collectible.cs可以访问生命属性

    //给个无敌时间
    private float invincibleTime = 2f;//无敌时间2秒

    private float invincibleTimer;//无敌计时器

    private bool isInvincible;//给个状态-是否处于无敌状态

    public GameObject bulletPrefab;//子弹

    //==============玩家的音效===============================

    public AudioClip hitClip;//受伤音效
    public AudioClip launchClip;//发射齿轮音效

    //==============玩家的方向的朝向=========================
    private Vector2 lookDirection = new Vector2(1, 0);//(动画)默认朝向右方

    //==============玩家的子弹数量============================
    [SerializeField ]//序列化一下 也能在属性面板直接调整
    private int curBulletCount;//当前子弹数量
    private int maxBulletCount = 10;//最大子弹数量

    public int MyCurBulletCount {
    get {
    return curBulletCount; } }
    public int MyMaxBulletCount {
    get {
    return maxBulletCount; } }//这样就能在齿轮子弹包BulletBag.cs那边进行访问了

    public static object pc {
    get; internal set; }

    Passform currentPassform;  //当前玩家处在的位置

    Rigidbody2D rbody;//先获取它的刚体组件
    Animator anim;//(动画)获取动画组件

    /// <summary>
    /// 背包系统
    /// </summary>
    public GameObject myBag;
    bool isOpen;//反复按同一个按键 实现打开和关闭效果
    

    /// <summary>
    /// 智能提示
    /// </summary>
    //无法实现在其他脚本中销毁提示,故在此脚本中限时销毁
    public float showTime = 3;
    private float showTimer;

    //智能提示框计时器
    public float tiptime = 6;
    private float tiptimer;

    //智能提示文本
    public Text tips;
    public GameObject tipsframe;

    void Start()
    {
   
        curBulletCount = 2;//一开始子弹数量为0
        currentHealth = 5;
        invincibleTimer = 0;//一开始是可以受到伤害的
        rbody = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();//(动画)获取动画组件
        UImanager.instance.UpdateHealthBar(currentHealth, maxHealth);//更新以下血条状态
        UImanager.instance.UpdateBulletCount(curBulletCount, maxBulletCount);

    }

  
    void Update()
    {
   

        //智能提示文本
        showTimer -= Time.deltaTime;//任务完成显示 计时器
        tiptimer -= Time.deltaTime;//提示框显示 计时器
        if (tiptimer<0)//超过时间就取消显示提示文本
        {
   
            tipsframe.SetActive(false);
        }
        if (showTimer + 5 < 0)//取消显示提示文本
        {
   
            tipsframe.SetActive(false);
        }
        if (currentHealth <= 2)//如果生命<=2了,则进行提示
        {
   
            tip();
        }
        if (curBulletCount == 0 && currentHealth !=0)//如果没有子弹了,则进行提示
        {
   
            tip();
        }

        



        OPenMyBag();//在Update里进行调用
        /** 
         * 测试左朝向有误 故暂改代码 
         * float horizontal = Input.GetAxis("Horizontal");//控制水平移动方向A: -1  D: 1   0
         float vertical = Input.GetAxis("Vertical");   //控制垂直移动方向 W: 1  S:-1  0

         Vector2 moveVector = new Vector2(horizontal, vertical);//(动画)
         if (moveVector.x != 0 || moveVector.y != 0) {
             lookDirection = moveVector;
         }//按键不按的时候是为0的
         anim.SetFloat("Look X", lookDirection.x);
         anim.SetFloat("Look Y", lookDirection.y);
         anim.SetFloat("Speed", moveVector.magnitude);
     **/

        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        Vector2 moveVector = new Vector2(horizontal, vertical);//将输入值存储在名为 moveVector 的 Vector2 变量中,而不是独立设置用于移动的 x 和 y

        /*检查 move.x 或 move.y 是否不等于 0
         * 使用 Mathf.Approximately 而不是 ==,这是因为计算机存储浮点数的方式意味着精度会有很小的损失
         * 所以,不应测试完美的相等性,因为最终结果应该是 0.0f 的运算可能会得出类似 0.0000000001f 的结果。Approximately 会考虑这种不精确性,如果除去这种不精确性可以认为数值相等,将返回 true
         * 本可以设置 lookDirection = moveVector,但这是另一种分配向量的 x 和 y 的方式
         */
        if (!Mathf.Approximately(moveVector.x, 0.0f) || !Mathf.Approximately(moveVector.y, 0.0f))
        {
   
            lookDirection.Set(moveVector.x, moveVector.y);
            lookDirection.Normalize();//在 lookDirection 上调用 Normalize,从而使长度等于 1。Vector2 类型存储位置,但也可以存储方向
        }

        anim.SetFloat("Look X", lookDirection.x);
        anim.SetFloat("Look Y", lookDirection.y);
        anim.SetFloat("Speed", moveVector.magnitude);


        //=========移动=================================================================
        Vector2 position = rbody .position;
        //position.x = position.x + 1f * moveX * speed* Time.fixedDeltaTime; //消除抖动把Time.deltaTime改成Time.fixedDeltaTime
        //position.y = position.y + 1f * moveY * speed* Time.fixedDeltaTime;
        //因为上面定义了moveVector 所以把上面的注释掉 换另一种写法
        position += moveVector * speed * Time.fixedDeltaTime;
        rbody .MovePosition ( position);//把transform.position = position;修改成刚体移动

        //=============无敌计时==========================================================
        if (isInvincible) {
   
            invincibleTimer -= Time.deltaTime;
            if (invincibleTimer < 0)
            {
   
                isInvincible = false; //倒计时结束以后(2秒),取消无敌状态
            }
        }
        //=============按下J键 并且子弹数量>0 进行攻击===================================================
        if (Input.GetKeyDown(KeyCode.J)&&curBulletCount >0)
        {
   

            Launch();

        }
        //=============按下 E 键 进行NPC交互
        if (Input.GetKeyDown(KeyCode.E)) {
   
            RaycastHit2D hit = Physics2D.Raycast(rbody.position, lookDirection, 2f,LayerMask .GetMask ("NPC"));//根据层级来进行索引 把NPC设为NPC层级 这样玩家发射的射线就只会和NPC触碰
            if (hit.collider != null) {
   
                NPCmanager npc = hit.collider.GetComponent<NPCmanager>();
                if (npc != null) {
   
                    npc.ShowDialog();//显示对话框
                }
            }

        }

        //==================玩家死亡结束游戏===================================
        //如果生命值为0,显示游戏结束字样,并销毁主角
        if (currentHealth == 0)
        {
   
            //GameOver.SetActive(true);
            //tip();
            //GameObject.Find("Ruby").GetComponent<PlayerController >().enabled = false;
            //gameObject.SetActive(false);
            Destroy(GameOverPlayer,2f);
            SceneManager.LoadScene(1);
        }

        //穿越
        if (currentPassform != null)
        {
   
            currentPassform.Pass(gameObject);
        }

    }
 

    /// <summary>
    /// 改变玩家的生命值
    /// </summary>
    /// <param name="amount"></param>
    public void ChangeHealth(int amount) {
   
        //如果玩家受到伤害
        if (amount < 0) {
   
            if (isInvincible == true) {
   

                return; //如果处于无敌状态就不让它进行下一步的伤害检测了

            }

            isInvincible = true;//如果不是无敌状态 改为true 让它受到这次伤害后就是无敌状态了 只让它受到一次伤害   
            anim.SetTrigger("Hit");//添加受伤动画
            AudioManager.instance.AudioPlay(hitClip);//播放受伤音效
            invincibleTimer = invincibleTime;//把时间进行重置 这样update里就能进行检测 它就开始减 如果小于0后它就解除无敌状态
        }

        //把玩家的生命值约束在0和最大值之间
        Debug.Log(currentHealth + "/" + maxHealth);
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
        UImanager.instance.UpdateHealthBar(currentHealth, maxHealth);//更新血条
        Debug.Log(currentHealth + "/" + maxHealth);
    }

    public void ChangeBulletCount(int amount) {
   
        curBulletCount = Mathf.Clamp(curBulletCount + amount, 0, maxBulletCount);//限制子弹数量在0-最大值之间
        UImanager.instance.UpdateBulletCount(curBulletCount, maxBulletCount);
    }

    public void Launch()
    {
   
        if (!UImanager.instance.hasTask)  //当没有任务的时候
        {
   
            return;
        }
        ChangeBulletCount(-1);//每次攻击减1个齿轮
        anim.SetTrigger("Launch");//播放攻击动画
        AudioManager.instance.AudioPlay(launchClip);//播放攻击音效
        GameObject bullet = Instantiate(bulletPrefab, rbody.position + Vector2.up * 0.5f
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值