U3D《真正的大冒险》(下)精讲教学

本文介绍了Unity游戏开发中UI界面的设计与实现方法,包括UIBaseScript基类及UIStartScript、UIOption、UILose、UILevel1等具体界面脚本的功能与使用。同时,还详细讲解了角色控制、事件触发机制以及相机跟随等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果这些内容对你有用,请做一棵蒲公英让知识的种子随风植入人的心里。
在下篇中我们将讲解UI界面的关系与玩家在场景中陷阱交互的机制。

另外给大家推荐一个做动画不错的插件叫做DOTween,http://dotween.demigiant.com/documentation.php.

UIBaseScript:主要作为UI界面的父类,其中包含场景进入,场景暂停,场景重置,场景结束四个功能,另外需要给预制体UI添加CanvasGroup组件以便我们控制场景的射线检测,交互,透明度等信息。

UIBaseScropt:

protected CanvasGroup canvasGroup;

    public virtual void Awake()
    {
        canvasGroup = GetComponent<CanvasGroup>();//获取CanvasGroup组件
    }
    public virtual void Enter() { } //UI入栈
    public virtual void Pause() { } //UI暂停
    public virtual void Resume() { } //UI重置
    public virtual void Exit() { } //UI出栈

UIStartScript:继承自父类UIBaseScript//用了DOTWEEN插件记得引入命名空间using DG.Tweening

public class UIStartScript : UIBaseScript {

    private Button OptionButton;
    private Button StartButton;
    public override void Awake()
    {
        base.Awake();//调用父类awake方法
        Debug.Log("UIStart Awake");
    }
    void Start()
    {
        OptionButton = transform.Find("BG/Option").GetComponent<Button>();
        OptionButton.onClick.AddListener(GoOption);
        StartButton = transform.Find("BG/Play").GetComponent<Button>();
        StartButton.onClick.AddListener(GoPlay);
    }
    public override void Enter()
    {
        //Debug.Log("UIStart Enter");
        //canvasGroup.alpha = 0.5f;
        //打开UI界面的交互
        canvasGroup.interactable = true;
        //开启UI简便动画(0-1)
        canvasGroup.DOFade(1,0.5f);
        //打开射线检测
        canvasGroup.blocksRaycasts = true;
    }
    public override void Pause()
    {
        //关闭UI界面的交互
        canvasGroup.interactable = false;
        //开启UI简便动画(1-0)
        canvasGroup.DOFade(0, 0.5f);
        //关闭射线检测
        canvasGroup.blocksRaycasts = false;
    }
    public override void Resume()
    {
        //打开UI界面的交互
        canvasGroup.interactable = true;
        //开启UI简便动画(0-1)
        canvasGroup.DOFade(1, 0.5f);
        //打开射线检测
        canvasGroup.blocksRaycasts = true;
    }
    public override void Exit()
    {

    }
    void GoOption()
    {
        //从start跳转设置界面
        UIManager.Instance.Load("Option");
    }
    void GoPlay()
    {
        //跳转关卡界面
        UIManager.Instance.Load("Level1");
    }

UIOption:选项界面,主要控制音乐播放与返回主页面

public class UIOption : UIBaseScript {

    Button backBtn;
    Button muteBtn;
    Image muteImage;
    private bool isMute;//bgm是静音
    private Sprite mute_on;
    private Sprite mute_off;
    public override void Awake()
    {
        base.Awake();
    }
    void Start()
    {
        backBtn = transform.Find("BG/Back").GetComponent<Button>();
        backBtn.onClick.AddListener(GoBack);
        muteBtn = transform.Find("BG/bg/Music/Button").GetComponent<Button>();
        muteBtn.onClick.AddListener(ControllBGM);
        muteImage = transform.Find("BG/bg/Music/Button").GetComponent<Image>();
        mute_on = muteImage.sprite;

        mute_off = Resources.Load<Sprite>("UI/Switch_off");
    }
    public override void Enter()
    {
        //打开UI界面的交互
        canvasGroup.interactable = true;
        //开启UI简便动画(0-1)
        canvasGroup.DOFade(1, 0.5f);
        //打开射线检测
        canvasGroup.blocksRaycasts = true;
    }
    public override void Pause()
    {

    }
    public override void Resume()
    {

    }
    public override void Exit()
    {
        //把当前脚本所在的游戏物体给删除

        //先隐藏界面 关闭交互
        canvasGroup.interactable = false;
        canvasGroup.DOFade(0, 0.5f);
        //关闭射线检测
        canvasGroup.blocksRaycasts = false;
    }
    void GoBack()
    {
        UIManager.Instance.Pop();
    }
    void ControllBGM()
    {
        isMute = !isMute;
        AudioManager.Instance.Mute = isMute;
        if(isMute)
        {
            muteImage.sprite = mute_off;
        }
        else
        {
            muteImage.sprite = mute_on;
        }
    }
}

UILose:插件控制结束界面的进出进入与CanvasGroup功能

public class UILose : UIBaseScript {

    Transform lose;
    Button replayBtn;
    Vector3 originalPos;

    public override void Awake()
    {
        lose = transform.Find("Panel/Lose").transform;
        originalPos = lose.position;
        replayBtn = lose.Find("RePlay").GetComponent<Button>();
        replayBtn.onClick.AddListener(Replay);
        base.Awake();
    }
    public override void Enter()
    {
        Debug.Log(lose);
        lose.DOLocalMoveY(0,0.5f);
        canvasGroup.interactable = true;
        canvasGroup.blocksRaycasts = true;
    }

    public override void Exit()
    {
        lose.position = originalPos;
        canvasGroup.interactable = false;
        canvasGroup.blocksRaycasts = false;
    }

    public void Replay()
    {
        UIManager.Instance.Pop();
    }
}

UILevel1:给摄像机添加CameraFollow脚本进行镜头跟随与重置退出关卡等

public class UILevel1 : UIBaseScript {

    CameraFollow cf;
    public override void Awake()
    {
        base.Awake();
    }

    public override void Enter()
    {
        Debug.Log("开始游戏了");
        if(cf ==null)
        {
            cf = Camera.main.gameObject.AddComponent<CameraFollow>();
        }
        cf.enabled = true;

    }
    public override void Resume()
    {
        Debug.Log("重新开始当前关卡");
        //1.重置人物的状态
        Hero.instance.Reset();
        //2.重置关卡中的每个陷阱中的ResetLevel脚本 执行rest方法
        ResetLevel[] res = FindObjectsOfType<ResetLevel>();
        for(int i=0;i<res.Length;i++)
        {
            res[i].Rest();
        }
    }
    public override void Exit()
    {
        cf.enabled = false;
    }

}

Hero:玩家的移动跳跃等,需要判断玩家是否在地面(不能连跳),玩家是否死亡等状态。

public static Hero instance;
    Rigidbody2D rig;
    public float speed = 5;
    public float force = 300;
    private bool dead;
    //玩家位置
    public Vector3 SavePos
    {
        get;
        set;
    }
    public bool isFly
    {
        get;
        set;
    }
    public bool isDead
    {
        get
        {
            return dead;
        }
        set
        {
            dead = value;
            if(dead)
            {
                //ToDo处理hero的事件
                //退出Lose界面
                UIManager.Instance.Load("UILose");
            }
        }
    }
    private void Awake()
    {
        instance = this;
    }
    void Start (){
        rig = GetComponent<Rigidbody2D>();
        SavePos = transform.position;
        stone1 = GameObject.Find("Stone1").transform.position;
        stone2 = GameObject.Find("Stone2").transform.position;
        stone3 = GameObject.Find("Stone3").transform.position;
        stone4 = GameObject.Find("Stone4").transform.position;
        leftsword = GameObject.Find("LeftSword").transform;
        rightsword = GameObject.Find("RightSword").transform;
        leftswordPos = leftsword.transform.position;
        rightswordPos = rightsword.transform.position;
    }
    void Update (){
        Motion();

    }
    void Motion()
    {
        if(isDead)
        {
            Debug.Log("英雄死了");
            rig.velocity = Vector2.zero;
            return;
        }
        //虚拟轴控制左右移动
        float hor = Input.GetAxis("Horizontal");
        //Hero添加一个速度
        rig.velocity = new Vector2(hor*speed,rig.velocity.y);
        //按下空格键跳跃
        if(Input.GetKeyDown(KeyCode.Space) && !isFly )
        {
            rig.AddForce(Vector2.up * force);
        }
    }
    //重置玩家状态
    public void Reset()
    {
        transform.position = SavePos;
        isDead = false;
        //重置人物的动画

    }

重点来袭!!三大事件(碰撞,触发,还原陷阱)
当玩家掉到地图下或者碰到能主动攻击玩家的怪物时候,会调用碰撞事件监测机制,造成玩家死亡!

public class CollisionEvent : MonoBehaviour {

    public UnityEvent collisionEvent;
    public bool HeroIsFly;

    void OnCollisionEnter2D(Collision2D other)
    {
        HeroIsFly = false;
        Hero.instance.isFly = HeroIsFly;
        collisionEvent.Invoke();
    }
    private void OnCollisionExit2D(Collision2D other)
    {
        HeroIsFly = true;
        Hero.instance.isFly = HeroIsFly;
    }
}

碰撞事件

当玩家在固定位置踩到触发器,会触发相应事件,采用触发机制,如站在指定位置跳跃可顶出砖块

public class TriggerEvent : MonoBehaviour {

    public UnityEvent triggerEvent;
    public bool isDead;
    private void OnTriggerEnter2D(Collider2D other)
    {
        //当Hero触发陷阱的时候调用triggerEvent
        triggerEvent.Invoke();
        Hero.instance.isDead = isDead;
    }
}

触发事件

当玩家死亡时,点击重置按钮,玩家会回到初始位置,这时候把玩家触发出来的陷阱反向触发回去,采用重置事件。

public class ResetLevel : MonoBehaviour {

    public UnityEvent ResetEvent;
    public void Rest()
    {
        ResetEvent.Invoke();
    }
}

重置陷阱机制
图片中对比两个脚本内容,当碰撞或者触发某个事件时,重置事件需要做的就是反向触发回去,如砖块图片为1,当碰撞图片编程2,重置事件就需要把图片在重置关卡的时候重置回1。

CameraFollow:最后一个相机跟随脚本,采用插值方式平滑处理,限制下X轴保持场景一致。

public class CameraFollow : MonoBehaviour {

    Transform target;
    void Start()
    {
        target = GameObject.Find("Hero").transform;
    }
    void LateUpdate () {
        Follow();

    }
    void Follow()
    {
        //x [-0.2,23];
        Vector3 pos = transform.position;
        pos.x = Mathf.Lerp(pos.x,target.position.x,1);
        pos.x = Mathf.Clamp(pos.x, -0.2f, 23);
        transform.position = pos;
    }
}

虽然只做了一个关卡,但是包括了整个游戏90%的内容,希望对你有所帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值