经典游戏案例:unity官方推荐3d跑酷

学习目标:实现跑酷核心算法

游戏画面

项目结构目录

部分核心代码

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 游戏管理器是一个状态机,根据当前的游戏状态,它将在状态之间切换。
/// </summary>
public class GameManager : MonoBehaviour
{
    /// <summary>
    /// 单例模式
    /// </summary>
    public static GameManager instance { get { return s_Instance; } }
    protected static GameManager s_Instance;

    public AState[] states;
    //返回栈顶的游戏状态
    public AState topState { get { if (m_StateStack.Count == 0) return null; return m_StateStack[m_StateStack.Count - 1]; } }
    //消耗品数据库
    public ConsumableDatabase m_consumableDatabase;
    //游戏状态栈
    protected List<AState> m_StateStack = new List<AState>();
    //游戏状态字典
    protected Dictionary<string, AState> m_StateDict = new Dictionary<string, AState>();
    //函数执行顺序:awake onenable start
    protected void OnEnable()
    {
        PlayerData.Create();
        s_Instance = this;

        m_consumableDatabase.Load();
        m_StateDict.Clear();

        if (states.Length == 0)
        {
            return;
        }
        //初始化游戏状态字典
        for (int i = 0; i < states.Length; ++i)
        {
            states[i].manager = this;
            m_StateDict.Add(states[i].GetName(), states[i]);
        }

        m_StateStack.Clear();
        PushState(states[0].GetName());
    }

    protected void Update()
    {
        if (m_StateStack.Count > 0)
        {
            m_StateStack[m_StateStack.Count - 1].Tick();
        }
    }

    #region 游戏状态管理
    /// <summary>
    /// 游戏状态间的切换
    /// </summary>
    /// <param name="newState"></param>
    public void SwitchState(string newState)
    {
        AState state = FindState(newState);
        if(state == null)
        {
            Debug.LogError("Can't find the state named " + newState);
            return;
        }
        
        m_StateStack[m_StateStack.Count - 1].Exit(state);
        state.Enter(m_StateStack[m_StateStack.Count - 1]);
        m_StateStack.RemoveAt(m_StateStack.Count - 1);
        m_StateStack.Add(state);
    }
    /// <summary>
    /// 返回上一步游戏状态,并移除栈顶游戏状态
    /// </summary>
    public void PopState()
    {
        if (m_StateStack.Count < 2)
        {
            Debug.LogError("Can't pop states, only one in stack.");
            return;
        }

        m_StateStack[m_StateStack.Count - 1].Exit(m_StateStack[m_StateStack.Count - 2]);
        m_StateStack[m_StateStack.Count - 2].Enter(m_StateStack[m_StateStack.Count - 2]);
        m_StateStack.RemoveAt(m_StateStack.Count - 1);

    }
    /// <summary>
    /// 进入新的游戏状态,并将其入栈
    /// </summary>
    /// <param name="name"></param>
    public void PushState(string name)
    {
        AState state;
        if(!m_StateDict.TryGetValue(name,out state))
        {
            Debug.LogError("Can't find the state named " + name);
            return;
        }

        if (m_StateStack.Count > 0)
        {
            m_StateStack[m_StateStack.Count - 1].Exit(state);
            state.Enter(m_StateStack[m_StateStack.Count - 1]);
        }
        else
        {
            state.Enter(null);
        }
        m_StateStack.Add(state);
    }

    /// <summary>
    /// 在字典中查找游戏状态
    /// </summary>
    /// <param name="statename"></param>
    /// <returns></returns>
    public AState FindState(string statename)
    {
        AState state;
        if (!m_StateDict.TryGetValue(statename, out state)){
            return null;
        }
        else
        {
            return state;
        }
    }
    #endregion
}
/// <summary>
/// 游戏状态,用栈结构来存放
/// </summary>
public abstract class AState:MonoBehaviour
{
    [HideInInspector]
    public GameManager manager;
    /// <summary>
    /// 进入目标游戏状态前要执行的操作
    /// </summary>
    /// <param name="from">从哪个状态进入</param>
    public abstract void Enter(AState from);
    /// <summary>
    /// 离开目标游戏状态后要执行的操作
    /// </summary>
    /// <param name="to"></param>
    public abstract void Exit(AState to);
    /// <summary>
    /// 在目标游戏状态中要执行的操作
    /// </summary>
    public abstract void Tick();
    /// <summary>
    /// 获取游戏状态名(返回字符串)
    /// </summary>
    /// <returns></returns>
    public abstract string GetName();
}

下载链接:https://gitee.com/unity_demo/carzy-dash

相关推荐
yj爆裂鼓手1 小时前
spine绑定骨骼运动工具&spine纹理压缩自动设置工具
游戏·unity
电脑玩家柒柒5 小时前
FreeToken:在游戏 PC 上跑 290B+ 前沿 MoE——带宽自适应执行的本地推理新范式
游戏
朋友圈自动点赞工具12 小时前
NAS游戏库自动下载新方案,Questarr部署教程
服务器·数据库·游戏·科技资讯
小尘要自信13 小时前
2026手机远控电脑横测:CMD、游戏按键、144帧...ToDesk/向日葵/RustDesk跨设备处理任务
游戏·智能手机·电脑
yangmu320313 小时前
《天国拯救2》MOD整合包安装教程与深度解析
游戏
政安晨16 小时前
政安晨【人工智能随笔】— 从像素到星际:游戏如何塑造了现代AI的二十年演进史 (读DeepMind的EVE宇宙AI研究有感)
人工智能·游戏·ai·智能体·deepmind·人工智能与游戏·智能体与游戏
发量惊人的中年网工16 小时前
游戏开服就被DDoS攻击怎么办?开服7分钟服务器被打穿的复盘与防护清单
运维·服务器·网络·安全·游戏
玖玥拾1 天前
Unity3D RPG 入门项目(十一)主角完整战斗、怪物自动刷新、四大类型技能系统
游戏·3d·unity·游戏引擎
学习星球1 天前
OpenHarness 全面配置教学——从游戏开发工作流引入
c++·游戏·ai·ai编程
狂云歌1 天前
2025年读书回顾,AI+游戏+历史
人工智能·学习·游戏