找回密码
 立即注册
查看: 422|回复: 2

Unity3D热更新LuaFramework入门实战(10)——示例程序

[复制链接]
发表于 2021-11-21 13:51 | 显示全部楼层 |阅读模式
终于到了本系列完结的时候了。
现在,大家对LuaFramework有个全方位的理解了吧!接下来通过一个例子总结ulua,作为“lua逻辑”的延伸,说明lua的写法。这个例子中玩家能够控制2D游戏角色走动,并且发射炮弹。
1、目标

制作如图所示的游戏,玩家可以通过键盘控制角色上下左右移动,角色有4个面向,走动过程中会播放行走动画。当玩家点击鼠标左键,角色会发射一颗炮弹。


2、游戏资源

使用下图所示的图片作为游戏角色(该图片来自rpg maker),在导入Unity后将它切割成12张小图。





使用如下图所示的图片作为炮弹。


在游戏场景中新建画布,画布下摆放一个名为Panel的面板,代表游戏场景。面板下有res和map两个子物体,map(Image)为一张场景图,role(Image)为游戏中的角色,bullet(Image)为游戏中的子弹(同一时间只能发射一颗子弹)。


Res子物体存放12张角色图片(Image),之后会使用这些资源替换map.role的图片,以实现动画效果。


然后将Panel做成预设,存放到SimpleGame目录下。并且在GameManager空物体上添加Game组件,以启动框架。


修改Packager.cs,在HandleExampleBundle添加如下代码,将SimpleGame目录下的预设打包。然后点击LuaFramework→Build Windows Resource打包。
//小游戏
AddBuildMap("SimpleGame" + AppConst.ExtName, "*.prefab", "Assets/SimpleGame");具体的框架设置请参加第一篇和第二篇,这里仅做简单描述。
3、编写行走代码

游戏使用UI组件,在CustomSettings.cs中添加如下两行,使tolua生成Image和Sprite相关的调用。
_GT(typeof(Image)),
_GT(typeof(Sprite)),打开main.lua(如何运行main.lua请参见第一篇)开始编写代码。程序从Main方法开始执行,使用LoadPrefab(请参见第二篇)加载之前打包的资源文件Panel。这里还定义几个变量,其中map代表游戏场景(panel.map),role代表游戏角色(panel.map.role),roleImage是游戏角色中的图片组件,roleRes代表各个面向的角色图片,比如roleRes[“UP”]将会包含panel.res中3张角色朝上的图。roleAnm代表当前角色的动画,每个面向有3个动画,对应于不同的图片。lastAnmTime代表展现角色动画帧的时间,用于控制动画播放速度。
--主入口函数。从这里开始lua逻辑
function Main()                                       
        LuaHelper = LuaFramework.LuaHelper;
        resMgr = LuaHelper.GetResManager();
        resMgr:LoadPrefab('SimpleGame', { 'Panel' }, OnLoadFinish);
end

local map
local role
local roleImage
local roleRes = {
        ["UP"] = {},
        ["DOWN"] = {},
        ["LEFT"] = {},
        ["RIGHT"] = {},
}
local roleAnm = 1;
local lastAnmTime = 0;

--加载完成后的回调--
function OnLoadFinish(objs)
    --暂略
end接着编写加载完成的回调方法OnLoadFinish,它处理下面几件事情。
1、使用Instantiate实例化面板,并且设置面板的坐标,具体请参见第5篇。
2、获取面板中的部件,给map、role、roleImage赋值。
3、获取素材res中的图片,赋值给roleRes,之后roleRes ["UP"],roleRes ["DOWN"],roleRes ["LEFT"],roleRes ["RIGHT"]都包含3张同面向不同动画的图片。
4、使用UpdateBeat:Add()初始化Update方法(具体参照第三篇)。
function OnLoadFinish(objs)
        --显示面板
        go = UnityEngine.GameObject.Instantiate(objs[0])
        local parent = UnityEngine.GameObject.Find("Canvas")
    go.transform:SetParent(parent.transform, false)
        --获取元素
        map = go.transform:FindChild("map").gameObject
        role = map.transform:FindChild("role").gameObject
        roleImage = role:GetComponent("Image")
        --获取素材
        local res = go.transform:FindChild("res").gameObject
        roleRes["DOWN"][1] = res.transform:FindChild("role (0)").gameObject:GetComponent("Image").sprite
        roleRes["DOWN"][2] = res.transform:FindChild("role (1)").gameObject:GetComponent("Image").sprite
        roleRes["DOWN"][3] = res.transform:FindChild("role (2)").gameObject:GetComponent("Image").sprite
        roleRes["LEFT"][1] = res.transform:FindChild("role (3)").gameObject:GetComponent("Image").sprite
        roleRes["LEFT"][2] = res.transform:FindChild("role (4)").gameObject:GetComponent("Image").sprite
        roleRes["LEFT"][3] = res.transform:FindChild("role (5)").gameObject:GetComponent("Image").sprite
        roleRes["RIGHT"][1] = res.transform:FindChild("role (6)").gameObject:GetComponent("Image").sprite
        roleRes["RIGHT"][2] = res.transform:FindChild("role (7)").gameObject:GetComponent("Image").sprite
        roleRes["RIGHT"][3] = res.transform:FindChild("role (8)").gameObject:GetComponent("Image").sprite
        roleRes["UP"][1] = res.transform:FindChild("role (9)").gameObject:GetComponent("Image").sprite
        roleRes["UP"][2] = res.transform:FindChild("role (10)").gameObject:GetComponent("Image").sprite
        roleRes["UP"][3] = res.transform:FindChild("role (11)").gameObject:GetComponent("Image").sprite
        --UpdateBeat
        UpdateBeat:Add(Update, self)
end编写Update方法,它根据用户输入改变坐标(具体参见第三篇),并且根据不同的移动方向设置角色图片素材,将roleImage.sprite替换成roleRes[方向][动画索引]。最后判断“if Time.time - lastAnmTime > 0.1 then”,每隔0.1秒切换一次动画。
--每帧执行
function Update()
       
        --移动
        local Input = UnityEngine.Input;
        local horizontal = Input.GetAxis("Horizontal");
        local verticla = Input.GetAxis("Vertical");
       
        local x = role.transform.position.x + horizontal
        local y = role.transform.position.y + verticla
        role.transform.position = Vector3.New(x,y,0)
        --转向
        if horizontal < 0 then
                roleImage.sprite = roleRes["LEFT"][roleAnm]
        elseif horizontal > 0 then
                roleImage.sprite = roleRes["RIGHT"][roleAnm]
        elseif verticla > 0 then
                roleImage.sprite = roleRes["UP"][roleAnm]
        elseif verticla < 0 then
                roleImage.sprite = roleRes["DOWN"][roleAnm]
        end
        --步伐(动画索引)
        if Time.time - lastAnmTime > 0.1 then
                roleAnm = roleAnm+1
                if roleAnm > 3 then roleAnm = 1 end
                lastAnmTime = Time.time
        end
       
end运行游戏,玩家可以通过键盘的方向键控制角色移动。


3、编写射击代码

在main.lua中添加炮弹相关的变量,如下所示。其中bullet代表炮弹元件(panel.map.bullet),lastShootTime 代表上一次发射炮弹的时间,bulletSpeedX代表炮弹的水平移动速度,bulletSpeedY代表炮弹的垂直移动速度,roleFace代表角色的面向。然后在OnLoadFinish中给bullet赋值。
local bullet
local lastShootTime = -100
local bulletSpeedX = 0
local bulletSpeedY = 0
local roleFace = 0

function OnLoadFinish(objs)
        ……
        --子弹元素
        bullet = map.transform:FindChild("bullet").gameObject
End在Update中给roleFace赋值。
--每帧执行
function Update()
       
        --移动
        ……
        --转向
        if horizontal < 0 then
                roleImage.sprite = roleRes["LEFT"][roleAnm]
                roleFace = 1
        elseif horizontal > 0 then
                roleImage.sprite = roleRes["RIGHT"][roleAnm]
                roleFace = 2
        elseif verticla > 0 then
                roleImage.sprite = roleRes["UP"][roleAnm]
                roleFace = 3
        elseif verticla < 0 then
                roleImage.sprite = roleRes["DOWN"][roleAnm]
                roleFace = 4
        end
        --步伐
        ……
end在Update中添加处理炮弹的代码,它处理如下几件事情。
1、炮弹在飞行1.2秒后,燃尽消失;
2、当玩家按下鼠标左键时,发射炮弹,根据角色面向,bulletSpeedX和bulletSpeedY会有不同的值。
3、根据bulletSpeedX和bulletSpeedY移动炮弹。
--每帧执行
function Update()
        ……
        --子弹
        if Time.time - lastShootTime > 1.2 then
                --消失
                if bullet.transform.position.x ~= -999 then
                        bullet.transform.position = Vector3.New(-999,-999,0)
                end
                --发射
                if Input.GetMouseButton(0) then
                        bullet.transform.position = Vector3.New(x,y,0)
                        if roleFace == 1 then
                                bulletSpeedX = -10
                                bulletSpeedY = 0
                        elseif roleFace == 2  then
                                bulletSpeedX = 10
                                bulletSpeedY = 0
                        elseif roleFace == 3 then
                                bulletSpeedX = 0
                                bulletSpeedY = 10
                        elseif roleFace == 4  then
                                bulletSpeedX = 0
                                bulletSpeedY = -10
                        end
                        lastShootTime = Time.time
                end
        else
                --运动
                local x = bullet.transform.position.x + bulletSpeedX
                local y = bullet.transform.position.y + bulletSpeedY
                bullet.transform.position = Vector3.New(x,y,0)
        end
end运行游戏,点击鼠标左键,角色发射炮弹。另外也可以用基于组件的方法实现,这里就不展开了。


最后依然到了广告时间:笔者即将出版的一本Unity3D实战类书籍《Unity3D网络游戏实战》。该书通过一个完整的多人坦克对战实例,详细介绍网络游戏开发过程中涉及到的知识和技巧。书中还介绍了服务端框架、客户端网络模块、UI系统的架构等内容。相信透过本书,读者能够掌握Unity3D网络游戏开发的大部分知识,也能够从框架设计中了解商业游戏的设计思路,感谢大家支持。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-11-21 14:00 | 显示全部楼层
课本出版 没有呀,速度呀
发表于 2021-11-21 14:03 | 显示全部楼层
很有帮助
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-5-15 04:01 , Processed in 0.137574 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表