一、定义一些简单的基本需求:
二、一些资源等...准备工作:
[ulua](http://www.ulua.org/index.html)
[模型](http://www.aigei.com/s?q=%E5%9D%A6%E5%85%8B&type=3d)
三、Unity(2017)UI搭建(UGUI)
选择角色界面我用的是RawImage+RenderTexture将模型渲染到Panel
四、代码编写(这里用的是ulua提供的框架)
1、为了方便我们先把AssetBundle模式关掉(关于AssetBundle我会后面另开文章单独介绍)
2、场景管理器(场景跳转)
lua-view-新建StartPanel
3、初始化
当运行的时候加载出所有Manager
游戏初始化管理器Game Manager
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using LuaInterface;
using System.Reflection;
using System.IO;
namespace LuaFramework {
public class GameManager : Manager {
protected static bool initialize = false;
private List downloadFiles = new List();
///
/// 初始化游戏管理器
///
void Awake() {
Init();
}
///
/// 初始化
///
void Init() {
DontDestroyOnLoad(gameObject); //防止销毁自己
CheckExtractResource(); //释放资源
Screen.sleepTimeout = SleepTimeout.NeverSleep;
Application.targetFrameRate = AppConst.GameFrameRate;
}
///
/// 释放资源
///
public void CheckExtractResource() {
bool isExists = Directory.Exists(Util.DataPath) &&
Directory.Exists(Util.DataPath + "lua/") && File.Exists(Util.DataPath + "files.txt");
if (isExists || AppConst.DebugMode) {
StartCoroutine(OnUpdateResource());
return; //文件已经解压过了,自己可添加检查文件列表逻辑
}
StartCoroutine(OnExtractResource()); //启动释放协成
}
IEnumerator OnExtractResource() {
string dataPath = Util.DataPath; //数据目录
string resPath = Util.AppContentPath(); //游戏包资源目录
if (Directory.Exists(dataPath)) Directory.Delete(dataPath, true);
Directory.CreateDirectory(dataPath);
string infile = resPath + "files.txt";
string outfile = dataPath + "files.txt";
if (File.Exists(outfile)) File.Delete(outfile);
string message = "正在解包文件:>files.txt";
Debug.Log(infile);
Debug.Log(outfile);
if (Application.platform == RuntimePlatform.Android) {
WWW www = new WWW(infile);
yield return www;
if (www.isDone) {
File.WriteAllBytes(outfile, www.bytes);
}
yield return 0;
} else File.Copy(infile, outfile, true);
yield return new WaitForEndOfFrame();
//释放所有文件到数据目录
string[] files = File.ReadAllLines(outfile);
foreach (var file in files) {
string[] fs = file.Split('|');
infile = resPath + fs[0]; //
outfile = dataPath + fs[0];
message = "正在解包文件:>" + fs[0];
Debug.Log("正在解包文件:>" + infile);
facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
string dir = Path.GetDirectoryName(outfile);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
if (Application.platform == RuntimePlatform.Android) {
WWW www = new WWW(infile);
yield return www;
if (www.isDone) {
File.WriteAllBytes(outfile, www.bytes);
}
yield return 0;
} else {
if (File.Exists(outfile)) {
File.Delete(outfile);
}
File.Copy(infile, outfile, true);
}
yield return new WaitForEndOfFrame();
}
message = "解包完成!!!";
facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
yield return new WaitForSeconds(0.1f);
message = string.Empty;
//释放完成,开始启动更新资源
StartCoroutine(OnUpdateResource());
}
///
/// 启动更新下载,这里只是个思路演示,此处可启动线程下载更新
///
IEnumerator OnUpdateResource() {
if (!AppConst.UpdateMode) {
OnResourceInited();
yield break;
}
string dataPath = Util.DataPath; //数据目录
string url = AppConst.WebUrl;
string message = string.Empty;
string random = DateTime.Now.ToString("yyyymmddhhmmss");
string listUrl = url + "files.txt?v=" + random;
Debug.LogWarning("LoadUpdate---->>>" + listUrl);
WWW www = new WWW(listUrl); yield return www;
if (www.error != null) {
OnUpdateFailed(string.Empty);
yield break;
}
if (!Directory.Exists(dataPath)) {
Directory.CreateDirectory(dataPath);
}
File.WriteAllBytes(dataPath + "files.txt", www.bytes);
string filesText = www.text;
string[] files = filesText.Split('\n');
for (int i = 0; i < files.Length; i++) {
if (string.IsNullOrEmpty(files[i])) continue;
string[] keyValue = files[i].Split('|');
string f = keyValue[0];
string localfile = (dataPath + f).Trim();
string path = Path.GetDirectoryName(localfile);
if (!Directory.Exists(path)) {
Directory.CreateDirectory(path);
}
string fileUrl = url + f + "?v=" + random;
bool canUpdate = !File.Exists(localfile);
if (!canUpdate) {
string remoteMd5 = keyValue[1].Trim();
string localMd5 = Util.md5file(localfile);
canUpdate = !remoteMd5.Equals(localMd5);
if (canUpdate) File.Delete(localfile);
}
if (canUpdate) { //本地缺少文件
Debug.Log(fileUrl);
message = "downloading>>" + fileUrl;
facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
/*
www = new WWW(fileUrl); yield return www;
if (www.error != null) {
OnUpdateFailed(path); //
yield break;
}
File.WriteAllBytes(localfile, www.bytes);
*/
//这里都是资源文件,用线程下载
BeginDownload(fileUrl, localfile);
while (!(IsDownOK(localfile))) { yield return new WaitForEndOfFrame(); }
}
}
yield return new WaitForEndOfFrame();
message = "更新完成!!";
facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
OnResourceInited();
}
void OnUpdateFailed(string file) {
string message = "更新失败!>" + file;
facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message);
}
///
/// 是否下载完成
///
bool IsDownOK(string file) {
return downloadFiles.Contains(file);
}
///
/// 线程下载
///
void BeginDownload(string url, string file) { //线程下载
object[] param = new object[2] { url, file };
ThreadEvent ev = new ThreadEvent();
ev.Key = NotiConst.UPDATE_DOWNLOAD;
ev.evParams.AddRange(param);
ThreadManager.AddEvent(ev, OnThreadCompleted); //线程下载
}
///
/// 线程完成
///
///
void OnThreadCompleted(NotiData data) {
switch (data.evName) {
case NotiConst.UPDATE_EXTRACT: //解压一个完成
//
break;
case NotiConst.UPDATE_DOWNLOAD: //下载一个完成
downloadFiles.Add(data.evParam.ToString());
break;
}
}
///
/// 资源初始化结束
///
public void OnResourceInited() {
#if ASYNC_MODE
ResManager.Initialize(AppConst.AssetDir, delegate() {
Debug.Log("Initialize OK!!!");
this.OnInitialize();
});
#else
ResManager.Initialize();
this.OnInitialize();
#endif
}
void OnInitialize() {
LuaManager.InitStart();
LuaManager.DoFile("Logic/Game"); //加载游戏
LuaManager.DoFile("Logic/Network"); //加载网络
NetManager.OnInit(); //初始化网络
Util.CallMethod("Game", "OnInitOK"); //初始化完成
initialize = true;
//类对象池测试
var classObjPool = ObjPoolManager.CreatePool(OnPoolGetElement, OnPoolPushElement);
//方法1
//objPool.Release(new TestObjectClass("abcd", 100, 200f));
//var testObj1 = objPool.Get();
//方法2
ObjPoolManager.Release(new TestObjectClass("abcd", 100, 200f));
var testObj1 = ObjPoolManager.Get();
Debugger.Log("TestObjectClass--->>>" + testObj1.ToString());
//游戏对象池测试
var prefab = Resources.Load("TestGameObjectPrefab", typeof(GameObject)) as GameObject;
var gameObjPool = ObjPoolManager.CreatePool("TestGameObject", 5, 10, prefab);
var gameObj = Instantiate(prefab) as GameObject;
gameObj.name = "TestGameObject_01";
gameObj.transform.localScale = Vector3.one;
gameObj.transform.localPosition = Vector3.zero;
ObjPoolManager.Release("TestGameObject", gameObj);
var backObj = ObjPoolManager.Get("TestGameObject");
backObj.transform.SetParent(null);
Debug.Log("TestGameObject--->>>" + backObj);
}
///
/// 当从池子里面获取时
///
///
void OnPoolGetElement(TestObjectClass obj) {
Debug.Log("OnPoolGetElement--->>>" + obj);
}
///
/// 当放回池子里面时
///
///
void OnPoolPushElement(TestObjectClass obj) {
Debug.Log("OnPoolPushElement--->>>" + obj);
}
///
/// 析构函数
///
void OnDestroy() {
if (NetManager != null) {
NetManager.Unload();
}
if (LuaManager != null) {
LuaManager.Close();
}
Debug.Log("~GameManager was destroyed");
}
}
}
这里是lua层的初始化 ↓
加载获取所有view文件夹文件:
新建并注册一个ctrl:
加载构造:
指定加载面板:
StartCtrl = {}
local this = StartCtrl
function StartCtrl.New()
return this
end
function StartCtrl.Awake()
panelMgr:CreatePanel('Start', InitEnd);
end
function InitEnd()
log("开始面板创建成功")
end
对应的调用方法在c#PanelManager中的CreatePanel方法
四、Assetbundle打包登录场景加载
AddBuildMap("Start" + AppConst.ExtName, "*.prefab", "Assets/Resources/Panels/Starpanel");
运行测试下:
五、业务层逻辑的处理(实现场景跳转)
先说一个简单的跳转处理(这里我们需要写自己的需求所以自己写一个管理器)
这里用到了LuaBehaviour中的一些回调
using UnityEngine;
using LuaInterface;
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine.UI;
namespace LuaFramework {
public class LuaBehaviour : View {
private string data = null;
private Dictionary buttons = new Dictionary();
protected void Awake() {
Util.CallMethod(name, "Awake", gameObject);
}
protected void Start() {
Util.CallMethod(name, "Start");
}
protected void OnClick() {
Util.CallMethod(name, "OnClick");
}
protected void OnClickEvent(GameObject go) {
Util.CallMethod(name, "OnClick", go);
}
///
/// 添加单击事件
///
public void AddClick(GameObject go, LuaFunction luafunc) {
if (go == null || luafunc == null) return;
buttons.Add(go.name, luafunc);
go.GetComponent
StartCtrl (加载面板)
StartCtrl = {}
local this = StartCtrl
function StartCtrl.New()
logWarn("StartCtrl.New--->>");
return this
end
function StartCtrl.Awake()
logWarn("StartCtrl.Awake--->>");
panelMgr:CreatePanel('Start', InitEnd);
end
function InitEnd(go)
log("开始面板创建成功")
behaviour = go:GetComponent("LuaBehaviour")
--(按钮实例,回调函数)
behaviour:AddClick(StartPanel.startBtn,OnStartBtnClick)
behaviour:AddClick(StartPanel.exitBtn,OnExitButtonClick)
end
function OnStartBtnClick()
log("开始按钮被点击了")
end
function OnExitButtonClick()
log("退出按钮被点击了")
end
StartPanel (获取组件)
--处理业务逻辑
StartPanel = { }
local this = StartPanel
function StartPanel.Awake(go)
gameObject = go
transform = go.transform
this.init()
end
function StartPanel.init()
--获取组件
this.startBtn = transform:Find("StartButton").gameObject
this.exitBtn = transform:Find("ExitButton").gameObject
end
六、场景管理器(管理页面跳转)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SceneMgr : MonoBehaviour {
//同步跳转
public void LoadScene(int index)
{
UnityEngine.SceneManagement.SceneManager.LoadScene(index);
}
public void LoadScene(string index)
{
UnityEngine.SceneManagement.SceneManager.LoadScene(index);
}
//异步跳转
public void LoadSceneAsync(int index)
{
StartCoroutine(LoadSceneA(index));
}
private IEnumerator LoadSceneA(int index)
{
AsyncOperation asyncOperation = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(index);
yield return asyncOperation;
}
}
lua中define:
sceneMgr = LuaHelper.GetSceneManager();
StartPanel点击事件:
function OnStartBtnClick()
log("开始按钮被点击了")
sceneMgr:LoadScene(1)
end
运行效果如下:
//cjson(lua表转json)
#!/usr/bin/env lua
-- usage: json2lua.lua [json_file]
--
-- Eg:
-- echo '[ "testing" ]' | ./json2lua.lua
-- ./json2lua.lua test.json
local json = require "cjson"
local util = require "cjson.util"
local json_text = util.file_load(arg[1])
local t = json.decode(json_text)
print(util.serialise_value(t))
七、场景二和场景一相同:
1.首先我们要用一个空物体初始化这个场景
我们这里没有用这种方法因为需要加载面板很多话不方便管理
2.需要注意的是OnLevelLoaded
我们需要去注册一个事件它才会去通知跳转(5.4以及高版本以上是需要注册一个事件,才会在跳转场景的时候发送通知低版本相反)
using UnityEngine;
using System.Collections;
using LuaInterface;
using UnityEngine.SceneManagement;
namespace LuaFramework {
public class LuaManager : Manager {
private LuaState lua;
private LuaLoader loader;
private LuaLooper loop = null;
LuaFunction levelLoaded;
// Use this for initialization
void Awake() {
loader = new LuaLoader();
lua = new LuaState();
this.OpenLibs();
lua.LuaSetTop(0);
LuaBinder.Bind(lua);
DelegateFactory.Init();
LuaCoroutine.Register(lua, this);
//注册事件
SceneManager.sceneLoaded += OnSceneLoaded;
}
public void InitStart() {
InitLuaPath();
InitLuaBundle();
this.lua.Start(); //启动LUAVM
this.StartMain();
this.StartLooper();
}
void StartLooper() {
loop = gameObject.AddComponent();
loop.luaState = lua;
}
//cjson 比较特殊,只new了一个table,没有注册库,这里注册一下
protected void OpenCJson() {
lua.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED");
lua.OpenLibs(LuaDLL.luaopen_cjson);
lua.LuaSetField(-2, "cjson");
lua.OpenLibs(LuaDLL.luaopen_cjson_safe);
lua.LuaSetField(-2, "cjson.safe");
}
void StartMain() {
lua.DoFile("Main.lua");
levelLoaded = lua.GetFunction("OnLevelWasLoaded");
//main.Call();
//main.Dispose();
//main = null;
}
//监听场景跳转事件的方法
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
OnLevelLoaded(scene.buildIndex);
}
//场景跳转回调
void OnLevelLoaded(int level)
{
if (levelLoaded != null)
{
levelLoaded.BeginPCall();
levelLoaded.Push(level);
levelLoaded.PCall();
levelLoaded.EndPCall();
}
if (lua != null)
{
lua.RefreshDelegateMap();
}
}
///
/// 初始化加载第三方库
///
void OpenLibs() {
lua.OpenLibs(LuaDLL.luaopen_pb);
lua.OpenLibs(LuaDLL.luaopen_sproto_core);
lua.OpenLibs(LuaDLL.luaopen_protobuf_c);
lua.OpenLibs(LuaDLL.luaopen_lpeg);
lua.OpenLibs(LuaDLL.luaopen_bit);
lua.OpenLibs(LuaDLL.luaopen_socket_core);
this.OpenCJson();
}
///
/// 初始化Lua代码加载路径
///
void InitLuaPath() {
if (AppConst.DebugMode) {
string rootPath = AppConst.FrameworkRoot;
lua.AddSearchPath(rootPath + "/Lua");
lua.AddSearchPath(rootPath + "/ToLua/Lua");
} else {
lua.AddSearchPath(Util.DataPath + "lua");
}
}
///
/// 初始化LuaBundle
///
void InitLuaBundle() {
if (loader.beZip) {
loader.AddBundle("lua/lua.unity3d");
loader.AddBundle("lua/lua_math.unity3d");
loader.AddBundle("lua/lua_system.unity3d");
loader.AddBundle("lua/lua_system_reflection.unity3d");
loader.AddBundle("lua/lua_unityengine.unity3d");
loader.AddBundle("lua/lua_common.unity3d");
loader.AddBundle("lua/lua_logic.unity3d");
loader.AddBundle("lua/lua_view.unity3d");
loader.AddBundle("lua/lua_controller.unity3d");
loader.AddBundle("lua/lua_misc.unity3d");
loader.AddBundle("lua/lua_protobuf.unity3d");
loader.AddBundle("lua/lua_3rd_cjson.unity3d");
loader.AddBundle("lua/lua_3rd_luabitop.unity3d");
loader.AddBundle("lua/lua_3rd_pbc.unity3d");
loader.AddBundle("lua/lua_3rd_pblua.unity3d");
loader.AddBundle("lua/lua_3rd_sproto.unity3d");
}
}
public void DoFile(string filename) {
lua.DoFile(filename);
}
// Update is called once per frame
public object[] CallFunction(string funcName, params object[] args) {
LuaFunction func = lua.GetFunction(funcName);
if (func != null) {
return func.LazyCall(args);
}
return null;
}
public void LuaGC() {
lua.LuaGC(LuaGCOptions.LUA_GCCOLLECT);
}
public void Close() {
//取消注册
SceneManager.sceneLoaded -= OnSceneLoaded;
loop.Destroy();
loop = null;
lua.Dispose();
lua = null;
loader = null;
}
}
}
3.在lua Main函数中接受回调
--主入口函数。从这里开始lua逻辑
function Main()
print("logic start")
end
--场景切换通知
function OnLevelWasLoaded(level)
print("回调函数执行了 --------"..level)
if level == 1 then--选塔克场景
--调用此面板点击事件
panelMgr:CreatePanel("SelectTank",SelectTankCtrl.CreateTankHandler)
end
collectgarbage("collect")
Time.timeSinceLevelLoad = 0
end
function OnApplicationQuit()
end
function SelectTankCtrl.CreateTankHandler(go)
log("开始面板创建成功")
behaviour = go:GetComponent("LuaBehaviour")
--(按钮实例,回调函数)
behaviour:AddClick(SelectTankPanel.LeftBtn,OnLeftBtnClick)
behaviour:AddClick(SelectTankPanel.RigthBtn,OnRigthButtonClick)
behaviour:AddClick(SelectTankPanel.EnterBtn,OnEnterButtonClick)
end
function OnLeftBtnClick()
log("向左按钮被点击了")
end
function OnRigthButtonClick()
log("向右按钮被点击了")
end
function OnEnterButtonClick()
log("进入游戏按钮被点击了")
end
4.根据情况角色模型是分开打包或者打包到一起
5.SelectTankPanel 获取相机
--获取Camera
this.Camera = transform:Find("Camera").gameObject
6.SelectTankCtrl(角色选择与加载逻辑代码)
SelectTankCtrl = {}
local this = SelectTankCtrl
local tanks = { }
local disPlayTankIndex = 1
function SelectTankCtrl.New()
logWarn("SelectTankCtrl.New--->>");
return this
end
function SelectTankCtrl.Awake()
logWarn("SelectTankCtrl.Awake--->>");
--panelMgr:CreatePanel('SelectTank', this.InitEnd);
panelMgr:CreatePanel("SelectTank",SelectTankCtrl.CreateTankHandler)
end
function SelectTankCtrl.CreateTankHandler(go)
log("开始面板创建成功")
behaviour = go:GetComponent("LuaBehaviour")
--(按钮实例,回调函数)
behaviour:AddClick(SelectTankPanel.LeftBtn,OnLeftBtnClick)
behaviour:AddClick(SelectTankPanel.RigthBtn,OnRigthButtonClick)
behaviour:AddClick(SelectTankPanel.EnterBtn,OnEnterButtonClick)
--获取加载角色
tankNames = {"Buggy","Cube"}
resMgr:LoadPrefab("Tanks",tankNames,this.InitTankHandler)
end
function SelectTankCtrl.InitTankHandler(gos)
print(gos[0].name)
print(gos[1].name)
local go = newObject(gos[0]);
--将预制体加载到相机并且固定坐标
go.transform:SetParent(SelectTankPanel.Camera.transform,false)
local go1 = newObject(gos[1]);
go1.transform:SetParent(SelectTankPanel.Camera.transform,false)
tanks[1] = go
tanks[2] = go1
for i=1, #tanks do
tanks[i]:SetActive(false)
end
ShowTank()
end
function ShowTank()
tanks[disPlayTankIndex]:SetActive(true)
for i = 1, #tanks do
if i ~= disPlayTankIndex then
tanks[i]:SetActive(false)
end
end
end
function OnLeftBtnClick()
log("向左按钮被点击了")
disPlayTankIndex = disPlayTankIndex - 1
if disPlayTankIndex == 0 then
disPlayTankIndex = #tanks
end
ShowTank()
end
function OnRigthButtonClick()
log("向右按钮被点击了")
disPlayTankIndex = disPlayTankIndex + 1
if disPlayTankIndex == #tanks + 1 then
disPlayTankIndex = 1
end
ShowTank()
end
function OnEnterButtonClick()
log("进入游戏按钮被点击了")
end
八、游戏场景
[场景搭建](https://blog.csdn.net/nicolelili1/article/details/72843163)
lua TankCtrl
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
end
c#(挂在角色上的)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaFramework;
public class TankCtrl : MonoBehaviour {
public void Awake()
{
Util.CallMethod("Tankctrl","Awake",gameObject);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
1.角色移动
2.角色控制器
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
--角色控制器
local characterController
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
--characterController = go:GetComponent("CharacterController")
characterController = gameObject:GetComponent("CharacterController")
end
function TankCtrl.Update()
horizontal = UnityEngine.Input.GetAxis("Horizontal")
vertical = UnityEngine.Input.GetAxis("Vertical")
--[[if horizontal ~= 0 or vertical ~= 0 then
dir = Vector3.New()
dir.x = horizontal
dir.y = -vertical
transform:Translate(dir)
end]]
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.W) then
characterController:SimpleMove(-transform.up * UnityEngine.Time.deltaTime * 650)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.S) then
characterController:SimpleMove(transform.up * UnityEngine.Time.deltaTime * 420)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
transform:Rotate(Vector3.back * 2)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
transform:Rotate(Vector3.forward * 2)
end
end
c#接收
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LuaFramework;
public class TankCtrl : MonoBehaviour {
public void Awake()
{
Util.CallMethod("TankCtrl", "Awake",gameObject);
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Util.CallMethod("TankCtrl", "Update", gameObject);
}
}
2.子弹发射
tankctrl
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
local bullet--子弹
local firPos--父物体
--角色控制器
local characterController
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
--characterController = go:GetComponent("CharacterController")
characterController = gameObject:GetComponent("CharacterController")
--子弹加载(返回到回调函数中)
resMgr:LoadPrefab("Bullet",{"RedBullet"},TankCtrl.loadHandler)
--firPos = child("FirePos")
firPos = transform:Find("FirePos")
print(firPos)
end
--返回的子弹
function TankCtrl.loadHandler(gos)
print(gos[0])
bullet = gos[0]
end
function TankCtrl.Update()
horizontal = UnityEngine.Input.GetAxis("Horizontal")
vertical = UnityEngine.Input.GetAxis("Vertical")
--[[if horizontal ~= 0 or vertical ~= 0 then
dir = Vector3.New()
dir.x = horizontal
dir.y = -vertical
transform:Translate(dir)
end]]
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.W) then
characterController:SimpleMove(-transform.up * UnityEngine.Time.deltaTime * 650)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.S) then
characterController:SimpleMove(transform.up * UnityEngine.Time.deltaTime * 420)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
transform:Rotate(Vector3.back * 2)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
transform:Rotate(Vector3.forward * 2)
end
--加载子弹(按下鼠标左键)
if UnityEngine.Input.GetMouseButtonDown(0) then
print(bullet)
--获取子弹
temp = newObject(bullet)
--设置父物体
temp.transform:SetParent(firPos,false)
--temp.transform.localScale = Vector3(1,1,1)
temp.transform.localScale = Vector3.one
temp.transform.localPosition = Vector3(0,0,0)
end
end
3.给子弹挂一个脚本
4.子弹的生成移动
BulletCtrl = {}
local this = BulletCtrl
BulletCtrl.gameObject = nil
BulletCtrl.transform = nil
--[[local gameObject = nil
local transform = nil--]]
function BulletCtrl:New(o,go)
--print(o)
o = o or{}
o = setmetatable(o,self)
self.__index = self
o.gameObject = go
o.transform = o.gameObject.transform
return o
end
--[[function BulletCtrl.Awake(go)
gameObject = go
transform = gameObject.transform
end--]]
function BulletCtrl:Update()
self.transform:Translate(-self.transform.forward * UnityEngine.Time.deltaTime * 50)
end
5.坦克发射子弹调用
require "Battle/BulletCtrl"
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
local bullet--子弹
local firPos--父物体
--储存子弹的表
local bullets = { }
--角色控制器
local characterController
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
--characterController = go:GetComponent("CharacterController")
characterController = gameObject:GetComponent("CharacterController")
--子弹加载(返回到回调函数中)
resMgr:LoadPrefab("Bullet",{"RedBullet"},TankCtrl.loadHandler)
--firPos = child("FirePos")
firPos = transform:Find("FirePos")
print(firPos)
end
function TankCtrl.loadHandler(gos)
print(gos[0])
bullet = gos[0]
end
function TankCtrl.Update()
horizontal = UnityEngine.Input.GetAxis("Horizontal")
vertical = UnityEngine.Input.GetAxis("Vertical")
--[[if horizontal ~= 0 or vertical ~= 0 then
dir = Vector3.New()
dir.x = horizontal
dir.y = -vertical
transform:Translate(dir)
end]]
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.W) then
characterController:SimpleMove(-transform.up * UnityEngine.Time.deltaTime * 250)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.S) then
characterController:SimpleMove(transform.up * UnityEngine.Time.deltaTime * 220)
end
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
transform:Rotate(Vector3.back * 2)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
transform:Rotate(Vector3.forward * 2)
end
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.P) then
--加载子弹(按下鼠标左键)
--if UnityEngine.Input.GetMouseButtonDown(0) then
print(bullet)
--获取子弹
temp = newObject(bullet)
--把每一个发射的子弹存入战斗子弹管理类
BattleCtrl.GetInstance().Bullets[temp] = bc
--将每个子弹存储
bc = BulletCtrl:New(nil,temp)
table.insert(bullets,bc)
--设置父物体
temp.transform:SetParent(firPos,false)
temp.transform.localScale = Vector3(1,1,1)
--temp.transform.localScale = Vector3.one
temp.transform.localPosition = Vector3(0,0,0)
temp.transform.parent = nil
--取消设置父物体
temp.transform.DetachChildren(firPos)
end
if table.getn(bullets) > 0 then
for i,v in ipairs(bullets) do
v:Update()
end
end
end
6.战斗时子弹射中敌人的管理类BattleCtrl
--模拟一个子弹类
BattleCtrl = {}
local this = BattleCtrl
BattleCtrl.Bullets = {}
function BattleCtrl.GetInstance()
return this
end
function BattleCtrl.OnTriggerEnter(go,other)
local enemyTank = go
bulletCtrl = this.Bullets[other.gameObject]
--把子弹和野怪(被击中的敌人)传递给bulletCtrl
bulletCtrl.Attack(other.gameObject, enemyTank)
end
添加子弹碰撞管理及销毁
require "Battle/BulletCtrl"
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
local bullet--子弹
local firPos--父物体
--储存子弹的表
local bullets = { }
--角色控制器
local characterController
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
--characterController = go:GetComponent("CharacterController")
characterController = gameObject:GetComponent("CharacterController")
--子弹加载(返回到回调函数中)
resMgr:LoadPrefab("Bullet",{"RedBullet"},TankCtrl.loadHandler)
--firPos = child("FirePos")
firPos = transform:Find("FirePos")
print(firPos)
end
function TankCtrl.loadHandler(gos)
print(gos[0])
bullet = gos[0]
end
function TankCtrl.Update()
horizontal = UnityEngine.Input.GetAxis("Horizontal")
vertical = UnityEngine.Input.GetAxis("Vertical")
--[[if horizontal ~= 0 or vertical ~= 0 then
dir = Vector3.New()
dir.x = horizontal
dir.y = -vertical
transform:Translate(dir)
end]]
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.W) then
characterController:SimpleMove(-transform.up * UnityEngine.Time.deltaTime * 250)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.S) then
characterController:SimpleMove(transform.up * UnityEngine.Time.deltaTime * 220)
end
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
transform:Rotate(Vector3.back * 2)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
transform:Rotate(Vector3.forward * 2)
end
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.P) then
--加载子弹(按下鼠标左键)
--if UnityEngine.Input.GetMouseButtonDown(0) then
print(bullet)
--获取子弹
temp = newObject(bullet)
--把每一个发射的子弹存入战斗子弹管理类
BattleCtrl.GetInstance().Bullets[temp] = bc
--将每个发射的子弹单个实例
bc = BulletCtrl:New(nil,temp)
table.insert(bullets,bc)
--设置父物体
temp.transform:SetParent(firPos,false)
temp.transform.localScale = Vector3(1,1,1)
--temp.transform.localScale = Vector3.one
temp.transform.localPosition = Vector3(0,0,0)
temp.transform.parent = nil
--取消设置父物体
temp.transform.DetachChildren(firPos)
end
if table.getn(bullets) > 0 then
for i,v in ipairs(bullets) do
v:Update()
end
end
end
7.挂在所有敌人身上用于反馈自身及撞击子弹
using LuaFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyTankCtrl : MonoBehaviour {
//tank检测到碰撞
private void OnTriggerEnter(Collider other)
{
//调用乱函数获取射击的子弹以及被击中的坦克
Util.CallMethod("BattleCtrl", "OnTriggerEnter", new object[] { this.gameObject, other });
//将other传给lua
}
}
8.子弹挂的脚本
using LuaFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletCtrl : MonoBehaviour {
public void Awake()
{
Util.CallMethod("BulletCtrl", "Awake", gameObject);
}
// Use this for initialization
void Start()
{
}
// Update is called once per frame
//void Update()
//{
// //Util.CallMethod("BulletCtrl", "Update", gameObject);
// //if (gameObject != null)
// //{
// // Destroy(gameObject,5);
// //}
//}
}
BulletCtrl = {}
local this = BulletCtrl
BulletCtrl.gameObject = nil
BulletCtrl.transform = nil
--[[local gameObject = nil
local transform = nil--]]
function BulletCtrl:New(o,go)
--print(o)
o = o or{}
o = setmetatable(o,self)
self.__index = self
o.gameObject = go
o.transform = o.gameObject.transform
return o
end
--[[function BulletCtrl.Awake(go)
gameObject = go
transform = gameObject.transform
end--]]
function BulletCtrl:Update()
self.transform:Translate(-self.transform.forward * UnityEngine.Time.deltaTime * 50)
end
--[[--碰撞完处理攻击业务
function BulletCtrl.Attack(bullet,enemy)
--bullet.self = nil
destroy(bullet)
destroy(enemy)
end--]]
--模拟一个子弹类
BattleCtrl = {}
local this = BattleCtrl
BattleCtrl.Bullets = {}
function BattleCtrl.GetInstance()
return this
end
function BattleCtrl.OnTriggerEnter(...)
local res = {...}
--tanke
local enemyTank = res[1].gameObject
print("我是坦克.................."..enemyTank.name)
--zidan
local bullet = res[2].gameObject
print("我是子弹.................."..bullet.name)
destroy(bullet)
--print("我是子弹.................."..bullet.name)
destroy(enemyTank)
--print("我是坦克.................."..enemyTank.name)
--[[bulletCtrl = this.Bullets[bullet]
--把子弹和野怪(被击中的敌人)传递给bulletCtrl
bulletCtrl.Attack(bullet, enemyTank)--]]
end
9.坦克管理类
require "Battle/BulletCtrl"
TankCtrl = {}
local this = TankCtrl
local gameObject
local transform
local bullet--子弹
local firPos--父物体
--储存子弹的表
local bullets = { }
--角色控制器
local characterController
function TankCtrl.GetInstance()
return this
end
function TankCtrl.Awake(go)
gameObject = go
transform = go.transform
characterController = gameObject:GetComponent("CharacterController")
--子弹加载(返回到回调函数中)
resMgr:LoadPrefab("Bullet",{"bc"},TankCtrl.loadHandler)
firPos = transform:Find("FirePos")
print(firPos)
end
function TankCtrl.loadHandler(gos)
print(gos[0])
bullet = gos[0]
end
function TankCtrl.Update()
horizontal = UnityEngine.Input.GetAxis("Horizontal")
vertical = UnityEngine.Input.GetAxis("Vertical")
--[[if horizontal ~= 0 or vertical ~= 0 then
dir = Vector3.New()
dir.x = horizontal
dir.y = -vertical
transform:Translate(dir)
end]]
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.W) then
characterController:SimpleMove(-transform.up * UnityEngine.Time.deltaTime * 250)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.S) then
characterController:SimpleMove(transform.up * UnityEngine.Time.deltaTime * 220)
end
if UnityEngine.Input.GetKey(UnityEngine.KeyCode.A) then
transform:Rotate(Vector3.back * 2)
elseif UnityEngine.Input.GetKey(UnityEngine.KeyCode.D) then
transform:Rotate(Vector3.forward * 2)
end
--if UnityEngine.Input.GetKey(UnityEngine.KeyCode.P) then
--加载子弹(按下鼠标左键)
if UnityEngine.Input.GetMouseButtonDown(0) then
print(bullet)
--获取子弹
temp = newObject(bullet)
--把每一个发射的子弹存入战斗子弹管理类
BattleCtrl.GetInstance().Bullets[temp] = bc
--将每个发射的子弹单个实例
bc = BulletCtrl:New(nil,temp)
table.insert(bullets,bc)
--设置父物体
temp.transform:SetParent(firPos,false)
temp.transform.localScale = Vector3(1,1,1)
--temp.transform.localScale = Vector3.one
temp.transform.localPosition = Vector3(0,0,0)
temp.transform.parent = nil
--取消设置父物体
temp.transform.DetachChildren(firPos)
end
if table.getn(bullets) > 0 then
for i,v in ipairs(bullets) do
v:Update()
end
end
end