java编写roguelike_Unity官方教程 Roguelike 笔记

本文详述如何使用Java在Unity中构建一个回合制Roguelike游戏。游戏包括回合移动、食物系统、帧动画、碰撞检测、UI界面、音效处理及游戏逻辑。通过Singleton模式管理游戏状态,实现敌我单位移动,以及关卡生成。文章涵盖代码技巧和关键组件的实现细节。
摘要由CSDN通过智能技术生成

任务:

构建一个回合制走格子的“Roguelike”类型小游戏。

玩家每次可以移动一个格子,同时消耗一个食物点;

食物点可以通过拾取地图中的食物获得;

敌人会攻击玩家并偷取食物点。

游戏组件:

渲染层 SpriteRenderer.SortingLayers

游戏中渲染顺序依次为Floor,Items,Units,渲染层低的物体绘制较晚,所以会遮挡渲染层高的物体。

Floor放置背景(Floor、OuterWall);

Item放置出口、障碍食物和苏打水(Exit、Wall、Food\Drink);

Units层放置玩家和敌人(Player、Enemy);

帧动画 Animation

帧动画控制器包括Player和两个Enemy。

Player的序列帧动画包含闲置、攻击、被攻击 (Idle,Chop,Hit)三个状态。

当Trigger.playerChop触发时,Idle立即转为Chop,1s后Chop自动转为Idle;

当Trigger.playerHit触发时,Idle立即转为Hit,1s后Hit自动转为Idle。

Enemy的序列帧动画包含闲置、攻击 (Idle,Attack)两个状态。

当Trigger.enemyAttack触发时,Idle立即转为Attack,1s后Attack自动转为Idle;

不同Enemy通过Override Controller共用状态机相同的帧动画控制器。

碰撞检测逻辑

设置碰撞逻辑层BlockingLayer,Player、Enemy、Wall的所有碰撞检测(BoxCollider2D)都将在这个层里进行。

Player和Enemy均为运动刚体(Kinematic Rigidbody2D),可通过物理系统移动,但不受环境力影响;

Player的碰撞器尺寸为0.9,防止角色移动时与周围发生不必要碰撞。

Exit、Food(Drink)为碰撞触发器(trigger),不会产生碰撞物理效果。

界面 UI

界面包括LevelImage和FoodText

LevelImage 在进入游戏时显示当前关卡数,然后隐藏;在游戏结束时显示成绩。

FoodText 显示游戏进程中的食物量

音效

Audio Source 包括背景音乐和音效。

背景音乐循环播放。

音效包含玩家移动音效、玩家攻击音效、玩家受伤音效、拾取食物音效,通过SoundManager类进行控制。

Code Tips:

SoundManager

播放指定音效 PlaySingle(AudioClip clip)

播放随机音效 RandomizeSfx (params AudioClip[] clips)

体系结构:

关卡和整体结构

关卡管理类 board manager

这个脚本会基于当前关卡的编号,自动随机生成每个关卡。

Code Tips:

对象串行化 [Serializable]

prefab实例化 Instantiate(original, position, rotation)

游戏管理类 game manager

加载关卡,管理分数。

Code Tips:

单例模式 Singleton

类似全局变量,使game manager不会在关卡开始时重置

Loader脚本组织Singleton,把loader脚本放在maincamera上,awake时建立singleton

初始化进程 Awake()

DontDestroyOnLoad(gameObject)

加载board manager类,随机生成关卡

获取组件 GetComponent<>()

通过 lock inspector对数组批量赋值

Enemy管理

使用List获取Enemy位置

清空上一关敌人,在InitGame()中清空List

协程MoveEnemies() 让敌人按一定顺序移动

Scene被装载后回调

OnLevelWasLoaded(int level)已停用,用OnSceneLoad(Scene scene, LoadSceneMode sceneMode)代替

在Awake()中加入SceneManager.sceneLoaded += OnSceneLoad;

删除Awake()中的InitGame(),InitGame()仅在OnSceneLoad()中使用(???)

游戏逻辑

moving object

实现player和enemy的移动功能。

Code Tips:

实现平滑移动

协程 StartCoroutine

计算平方 sqrMagnitude 比 magnitude 更有效率

float.Epsilon 替代 0

Vector3 把一个点直线移动到目标点 Vector3.MoveTowards(current, target, maxDistanceDelta)

RigidBody2D移动到指定位置 RigidBody2D.MovePosition(position)

尝试移动,泛型 T

泛型方法定义了尝试移动的过程,由子类来决定自己关心的地形物体和处理方法。

关键字 abstract virtual override out

RaycastHit2D Physics2D.Linecast 光线投射碰撞检测 (使用时禁用自身碰撞器,防止射线碰撞到自身)

player

player交互类,继承自moving object

Code Tips:

变量不在Inspector中显示 [HideInInspector]

在Update()中进行移动

调用AttemptMove(T),指定泛型T为期望交互组件Wall

OnCantMove Chop动画触发,Wall实现可破坏效果(Wall.DamageWall(loss))

回调trigger碰撞检测,进行对象交互 OnTriggerEnter2D (Collider2D other)

到达Exit处时加载延时下一关Invoke(methodName, timeDelay);

重新加载场景

Application.LoadLevel(Application.loadedLevel)已过时,

用SceneManager.LoadSceneAsync(0);替代

对象禁用(隐藏?) enabled = false,

当player对象被禁用时(OnDisable()),利用Singleton保存数据

enemy

enemy交互类,继承自moving object

Code Tips:

初始化时注册GameManager的List,调用 GameManager.instance.AddEnemyToList(this)

敌人移动,由GameManager调用MoveEnemy()

调用AttemptMove(T),指定泛型T为期望交互组件Player

OnCantMoveAttack动画触发,Player受伤并触发Hit动画

(Player.LoseFood(playerDamage))

每隔一回合移动一次

通过player和enemy当前位置判断移动方向

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值