该系列是热更新四部曲(siki学院的03,04属于付费课程,暂时搁置)
热更新第一季《Assetbundle》
热更新第二季《Lua编程》
热更新第三季《xLua基础》
热更新第四季《xLua案例》
AssetBundle(创建打包)入门学习(基于Unity2017)
//改名AssetBundle_Write
//写入AssetBundle
using System.IO;
using UnityEditor;
public class AssetBundle_Write
{
[MenuItem("Assets/Build AssetBundles")]//按钮在菜单栏的位置
static void BuildAllAssetBundles()
{
string dir = "AssetBundles";//是工程根目录,不是Unity的那个Assets目录
if (Directory.Exists(dir)==false)
{
Directory.CreateDirectory(dir);
}
//目录,模式,平台
BuildPipeline.BuildAssetBundles(
dir,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows64);
}
}
//在工程根目录,不是Assets改根目录
//名字和后缀名是标记时填的
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEditor;
public class AssetBundle_Read : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
ReadAssetBundle();
}
void ReadAssetBundle()
{
AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/plane.unity3d");//必须加后缀
GameObject prefab = ab.LoadAsset<GameObject>("plane");//可以不加后缀
Instantiate(prefab);
}
// Update is called once per frame
void Update()
{
}
}
模型 类型 时间
更新频率 时间/同时加载 共享 小资源汇总 版本后缀区别
一个assetbundle==一组
//两个预制体,用同一种贴图、材质
//不给贴图、材质做标记。打包后大小
//给贴图、材质做标记。打包后大小
//写AssetBundle(ab)时的方法
BuildPipeline.BuildAssetBundles(
dir,
BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows64);
}
//第二个参数BuildAssetBundleOptions,压缩方式
LZMA,时空比大(时间复杂度较大,空间复杂度较小)
LZ4,时空比小
//以下以最大的文件比较,2050(LZMA)<2643(LZ4)<2845(不压缩)
//分享是shade,shard是碎片(这里翻译名字错了)
//只有LZ4有提示
......
Assets:#资源
- Assets/Prefabs/Plane.prefab
Dependencies:#依赖
- D:/Data/Projects/Unity/AssetBundle/AssetBundles/shard.unity3d
//使用时,保证先加载了贴图和材质,再加载引用材质的/贴图的预制体。实际材质、贴图放前放后没影响(?)
//保证的是使用时(比如实例预制体),改加载的都加载了
//以下是读ab的代码
void ReadAssetBundle()
{
//AssetBundle m = AssetBundle.LoadFromFile("AssetBundles/shard.unity3d");//材质、贴图(命名一样了)
AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/plane.unity3d");//必须加后缀
//
GameObject prefab = ab.LoadAsset<GameObject>("plane");//使用材质、贴图
AssetBundle m = AssetBundle.LoadFromFile("AssetBundles/shard.unity3d");//材质、贴图(命名一样了)
//
Instantiate(prefab);//对应第三张图
}
void Start()
{
LoadAssetBundleFromMemory("AssetBundles/plane.unity3d");
}
void LoadAssetBundleFromMemory(string path)//内存同步读取
{
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync( File.ReadAllBytes( path ) );
AssetBundle ab = request.assetBundle;
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name = path.Substring(path.LastIndexOf("/") + 1);//截取左后一个"/"后面的(不包括/)
name = name.Remove(name.IndexOf("."));//移除.后缀
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
IEnumerator LoadAssetBundleFromMemoryAsync(string path)//内存异步读取
{
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
//
yield return request;
//
AssetBundle ab = request.assetBundle;
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name = path.Substring(path.LastIndexOf("/") + 1);//截取左后一个"/"后面的(不包括/)
name = name.Remove(name.IndexOf("."));//移除.后缀
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
void Start()
{
string path = "AssetBundles/plane.unity3d";
LoadAssetBundleFromFile( path );//文件读取
}
void LoadAssetBundleFromFile(string path)
{
AssetBundle ab = AssetBundle.LoadFromFile( path );//必须加后缀
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name = path.Substring(path.LastIndexOf("/") + 1);//plane.unity3d
name = name.Remove(name.IndexOf("."));//plane
//
GameObject prefab = ab.LoadAsset<GameObject>( name );
//
Instantiate(prefab);//使用材质、贴图
}
void Start()
{
string path = "AssetBundles/plane.unity3d";
StartCoroutine(LoadAssetBundleFromFileAsync(path) ) ;//文件读取
}
IEnumerator LoadAssetBundleFromFileAsync(string path)
{
AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
//
yield return request;
//
AssetBundle ab = request.assetBundle;
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name = path.Substring(path.LastIndexOf("/") + 1);//截取左后一个"/"后面的(不包括/)
name = name.Remove(name.IndexOf("."));//移除.后缀
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
//问题是要去掉以下代码
if (string.IsNullOrEmpty(www.error))
{
print("www错误"+www.error);
yield break;
}
void Start()
{
string path_www = @"file://D:\Data\Projects\Unity\AssetBundle\AssetBundles\plane.unity3d";//\\或\\\都可以
StartCoroutine(LoadAssetBundleFromWWWAsync(path_www));
}
IEnumerator LoadAssetBundleFromWWWAsync(string path)//内存异步读取
{
//缓存
while (Caching.ready == false)//当前缓存
{
yield return null;
}
//请求
WWW www=WWW.LoadFromCacheOrDownload(path, 1);//路径,版本
//
yield return www;
print("W3"+www);
//
if (string.IsNullOrEmpty(www.error))
{
print("www错误"+www.error);
yield break;
}
//assetBundle
AssetBundle ab = www.assetBundle;
print("ab"+ab);
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name = path.Substring(path.LastIndexOf("\\") + 1);//截取左后一个"/"后面的(不包括/)
name = name.Remove(name.IndexOf("."));//移除.后缀
print("name"+name);
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
//尝试2017,Sphere是从2018拖过来的,实例时发生警告,broken prefab
//plane是在2017做的实例
//解决是在2017再做预制体
//视频的版本是2017.1.0f3
//我的版本是2018.4.32.32f1,www过时了,但是还可以用
//经过测试,不是版本问题
//去掉下面的代码就有了
//猜想贴图材质没加载导致break,结果用一个没贴图材质的Cube、3D Text也显示不了。总结就是以下代码删除
if (string.IsNullOrEmpty(www.error))
{
print("www错误"+www.error);
yield break;
}
任务2:源码工程、PPT.zip【Server服务器】
//注意通过
//跟www的本地加载差不多,要注意的是处理名字时,一个是"",一个是"/"。所以加判断
//视频localhost就可以访问网页,使用到unity
//我是localhost访问不到网页,localhost:端口号可以访问到网页,能使用到unity
string path_www = @"file://D:\Data\Projects\Unity\AssetBundle\AssetBundles\plane.unity3d";//\\或\\\都可以
string path_download= @"http://localhost:56201/AssetBundles/plane.unity3d";//\\或\\\都可以
path.Substring(path.LastIndexOf("/") + 1);
void Start()
{
string path_www = @"file://D:\Data\Projects\Unity\AssetBundle\AssetBundles\plane.unity3d";//\\或\\\都可以
string path_download= @"http://localhost:56201/AssetBundles/plane.unity3d";//\\或\\\都可以
StartCoroutine(LoadAssetBundleFromWWWAsync(path_download));
}
IEnumerator LoadAssetBundleFromWWWAsync(string path)//内存异步读取
{
//缓存
while (Caching.ready == false)//当前缓存
{
yield return null;//等待加载完成
}
//请求
WWW www=WWW.LoadFromCacheOrDownload(path, 1);//路径,版本
yield return www;
//assetBundle
AssetBundle ab = www.assetBundle;
//
string name = GetName(path);
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
string GetName(string path)
{
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name;
if (path.Contains("file"))
{
name = path.Substring(path.LastIndexOf("\\") + 1);//截取左后一个"\"后面的(不包括/)
}
else if (path.Contains("http"))
{
name = path.Substring(path.LastIndexOf("/") + 1);//截取左后一个"/"后面的(不包括/)
}
else
{
throw new System.Exception("异常");
}
name = name.Remove(name.IndexOf("."));//移除.后缀
print("名字" + name);
return name;
}
//变量一,资源来源
从本地
从服务器
//变量二,操作方式
方式一取值
方式二取值
下载(没全讲)
void Start()
{
string path_www = @"file://D:\Data\Projects\Unity\AssetBundle\AssetBundles\plane.unity3d";// //或///都可以
string path_download= @"http://localhost:56201/AssetBundles/plane.unity3d";//\\或\\\都可以
StartCoroutine(LoadAssetBundleFromUnityWebServerAsync(path_www));
}
string GetName(string path)
{
//比如"AssetBundles/plane.unity3d",我要得到"plane"
string name;
if (path.Contains("file"))
{
name = path.Substring(path.LastIndexOf("\\") + 1);//截取左后一个"\"后面的(不包括/)
}
else if (path.Contains("http"))
{
name = path.Substring(path.LastIndexOf("/") + 1);//截取左后一个"/"后面的(不包括/)
}
else
{
throw new System.Exception("异常");
}
name = name.Remove(name.IndexOf("."));//移除.后缀
print("名字" + name);
return name;
}
#region UnityWebServer
IEnumerator LoadAssetBundleFromUnityWebServerAsync(string path)//内存异步读取
{
//请求
//UnityWebRequest request = UnityWebRequest.GetAssetBundle(path);过时
//yield return request.Send();过时
//
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(path);
yield return request.SendWebRequest();//等待加载完成
AssetBundle ab;
if (false)//方式一
{
ab = DownloadHandlerAssetBundle.GetContent(request);
}
else if (true)//方式二
{
ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
}
//
string name = GetName(path);
//
GameObject prefab = ab.LoadAsset<GameObject>(name);
//
Instantiate(prefab);
}
void GetAllDependenciesByManifest()
{
//得到manifest
AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
AssetBundleManifest manifest = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//名字是固定的,AssetBundles.manifest是取不到的
foreach (string name in manifest.GetAllAssetBundles())
{
print(name);
}
string[] strArr = manifest.GetAllDependencies("plane.unity3d");
foreach (string name in strArr)
{
print(name);
}
}
Unity-Technologies/AssetBundles-Browser
//拖到Editor里面,窗口就有AssetBundle Browser的选项
//StreamingAssets不压缩
官网
B站
菜鸟
推荐【解压后文件夹5.1,里面的SciTE是编辑器】 Lua for Windows v5.1.5-52 Released
//编辑器有很烦的中文编码问题
--[[模块
require "module"
--require ("module")
--m=require ("module")
print(module.num1)
print(module.num2)
module.func1();
func2();
--]]
--print("HH");
--11
--[[注释
print("HH");
--]]
--[[type
print(type(1));
print(type("aa"));
print(type(H));
print(type(type));
print(type(print));
print(type(true));
print(type(nil));
--]]
--[[table
table1={key1="value1", key2="value2", key3=2}
print(table1)
print(table1.key1)
print(table1["key2"])
print("长度"..#table1)--有key,取不到最大索引
--
table.key1=nil
table1=nil
--
table2={"value1", "value2",2}
print(table2[0])
print(table2[2])
table2[4]="wr"
table2[1]=nil
print("长度"..#table2)--取得最大索引
--遍历
for k, v in pairs(table2) do
print(k .. " : " .. v)
--赋值即引用
table1={"句芒",name="鬼车"}
table2=table1;
table2[3]="天吴"
for k,v in pairs(table1)
do
print(k,v)
end
table2=nil
print(table1)
table1=nil
print(table1)
--连接
table1={"相柳","强良","天吴","鬼车"}
print(table.concat(table1))
print(table.concat(table1,"、"))
print(table.concat(table1,"、",3,4))
--插入
table1={"相柳","强良","天吴","鬼车"}
table.insert(table1,"句芒")
for k,v in pairs(table1)
do
print(k,v)
end
table.insert(table1,2,"萧摩柯")
for k,v in pairs(table1)
do
print(k,v)
end
--删除,索引连续
table1={"相柳","强良","天吴","鬼车"}
table.remove(table1,2)
for k,v in pairs(table1)
do
print(k,v)
end
--排序、最大值
table1={2,34,5,1,8,9}
table.sort(table1)
for k,v in pairs(table1)
do
print(k,v)
end
function maxn(tab)
local maxValue=0;
for k,v in pairs(tab)
do
if(v>maxValue)
then
maxValue=v
end
end
return maxValue
end
print(maxn(table1))
end
--]]
--[[元表
table1={"相柳","强良","天吴","鬼车"}
metatable1={}
table1=setmetatable(table1,metatable1);
--table1=setmetatable({"相柳","强良","天吴","鬼车"},{})
print(table1[1])
print(metatable1[1])
--地址一样
print(metatable1)
print(getmetatable(table1))
--__metatable,禁止访问元表
table1=setmetatable({"相柳","强良","天吴","鬼车"},{__metatable="禁止访问元表"})
print(table1)
print(getmetatable(table1))
--__index,处理超范围的key
table1={"相柳","强良","天吴","鬼车"}
metatable1={__index=function()
return "句芒"
end}
table1=setmetatable(table1,metatable1);
print(table1[5])
--
table1={"相柳","强良","天吴","鬼车"}
table2={}
table2[5]="句芒5"
metatable1={__index=table2}
table1=setmetatable(table1,metatable1);
print(table1[5])
--__newIndex,新索引走元表不走原表
table1=setmetatable({oldKey="相柳"},{__newindex=metatable1});
table1.oldKey="句芒"
print(table1.oldKey,metatable1.oldKey)
table1.newKey="烛九阴"--走元表
print(table1.newKey,metatable1.newKey)
--__newIndex,新增的走元表步骤
table1={}
table1=setmetatable({oldKey="相柳"},{__newindex=
function(table1, key, value)
print("__newindex起作用")
rawset(table1, key, "\""..value.."\"")
end
})
table1.oldKey="王猛"
table1.newKey="王镇恶"
--__newIndex,新增的放到另一个表
table1={}
table1={"后土"}
table2={}
metatable1={__newindex=table2}
table1=setmetatable(table1,metatable1);
table1[2]="元英"
print(table1[2], table2[2])
--__add,将表2insert到表1
table1={"后土"}
table2={"李虎","慕容垂"}
metatable1={__add=function(tab,newTab)
local length=0
for k,v in pairs(tab)
do
if(k>length)
then
length=k
end
end
for k,v in pairs(newTab)
do
table.insert(tab,length+k,v)
end
return newTab
end}
table1=setmetatable(table1,metatable1)
addTab=table1+table2
for k,v in pairs(table1)
do
print(v)
end
--__call,表当 函数 时 调用
table1={"后土"}
metatable1={
__call=function(tab,arg)
print(arg)
end
}
table1=setmetatable(table1,metatable1)
print(table1(5))
--__tostring,打印输出
table1={"后土","李虎","慕容垂"}
metatable1={
__tostring=function(tab)
str=""
for k,v in pairs(tab)
do
str=str..v
end
return str
end
}
table1=setmetatable(table1,metatable1)
print(table1)
--]]
--[[if
if(nil) then
print("nil==true");
else
print("nil==false");
end
a=10
if(a<3 then
print("1");
else if(a<8) then
print("2");
else
print("3");
end
--]]
--[[number
print(type(2))
print(type(2.2))
print(type(0.2))
print(type(2e+1))
print(type(0.2e-1))
print(type(7.8263692594256e-06))
print("2" + 6)
print("2" + "6")
print("2 + 6")
print("-2e2" * "6")
--print("error" + 1)
--]]
--[[运算符
a=2.2
b=2
print(a+b)
print(a-b)
print(a/b)
print(a%b)
print(a^b)
print(true and false)
print(true or false)
print(not true)
--]]
--[[转义符
path1="C:\Users\Desktop"
path2="C:\\Users\\Desktop"
path3="D:\\Users\\Desktop"
print(path1)
print(path2.."\n"..path3)
--]]
--[[string
string1 = "this is string1"
string2 = 'this is string2'
print(string1)
print(string2)
print(html)
--连接
print("a" .. 'b')
print(157 .. 428)
print(#"a赵云")--长度
--]]
--[[string
str="home.It feels good to be home"
print("大写:" .. string.upper(str) )
print("小写:" .. string.lower(str) )
print("长度:" .. string.len(str) )
print("长度:" .. #str )
--
print("替换:" .. string.gsub(str,"home", "country", 1))--次数
print("截取:" .. string.sub(str,1,7))--索引
--
print("查找:" .. string.find(str, "home", 2))--第几个的左右索引,超过就返回比如最后一个
--
print("复制:" .. string.rep(str,2) )--复制
print("反转:".. string.reverse(str) )
--
print(string.format("%2d+%3d=%4d",1,4,(1+4)))--format
print(string.format("用户:%s,密码:%s","赵云","12345") )
--
print( string.char(66))
print( string.byte('A') )
--正则
for word in string.gmatch(str, "%a+") do
print(word)
end
--]]
--[[function 阶乘
function fact(n)
if(n==1) then
return n
else
return n*fact(n-1)
end
end
print(fact(5))
fact2=fact
print(fact2(3))
--
--]]
--[[数组
arr={"帝江","奢比尸","斛律金"}
for i=-1,3 do--start,end
print(arr[i])
end
--
arr={{"帝江","奢比尸","斛律金"},{"元宏","刘裕","宗悫"}}
for i=1,2 do
for j=1,3 do
print(arr[i][j])
end
end
--]]
--[[迭代器 pairs ipairs
arr={"帝江","奢比尸","斛律金"}
arr[5]="元宏"
for k,v in pairs(arr) do
print(k,v)
end
for k,v in ipairs(arr) do
print(k,v)
end
--平方
function square(state,control)
if(control
--[[function 类委托、匿名
function fun(tab, fun)
for k,v in pairs(tab) do
fun(k, v)
end
end
function fun1(k, v)
print(k..":"..v)
end
function fun2(k, v)
print(k.."-"..v)
end
tab1={key1="高长恭",key2="斛律光"}
tab2={key1="韦睿",key2="陈庆之"}
fun(tab1, fun1)
fun(tab2, fun2)
--匿名
fun(tab1, function(k,v)
print(k.."+"..v);
end)
a=function(k,v)
print(k.."+"..v);
end
--]]
--[[function 可变参数
function average(...)
res=0
for k,v in pairs(arg) do
res=res+v
end
print(res/#arg)
end
average()
average(1,2)
average(3,4,5)
average(6,7,8,9)
--去除长度
function average(...)
local arg={...}
res=0
for k,v in pairs(arg) do
res=res+v
end
print(res/#arg)
end
average()
average(1,2)
average(3,4,5)
average(6,7,8,9)
--]]
--[[全局、局部变量
function fun1()
a=1
local b=2
end
fun1()
print(a,b)
--
do
a=3
local b=4
end
print(a,b)
--]]
--[[多变量赋值
a,b,c=1,2,"qwer"
print(a,b,c)
a,b,c=1,2
print(a,b,c)
a,b=1,2,"qwer"
print(a,b,c)
function fun1()
return 1,2
end
--
a=fun1()
print(a)
a,b=fun1()
print(a,b)
--]]
--[[循环 while for
a=0
while a<10 do
a=a+1
if a%2==1 then
print(a)
end
end
--
for i=1,10,2 do
print(i)
end
for i=10,1,-1 do
print(i)
end
--
a=1
repeat
a=a+1
print(a)
until(a>5)
--嵌套
for i=1,10 do
j=1
while j<=i do
print(j)
j=j+1
end
end
--
for i=1,10 do
j=1
repeat
print(j)
j=j+1
until j>i
end
--]]
--[[协程
--resume
function add(a,b)
print(a+b)
end
co=coroutine.create(add)
coroutine.resume(co,1,3)
--wrap
function add(a,b)
print(a+b)
end
co=coroutine.wrap(add)
co(1,5)
--yield(),暂停,二次不用传参
function add(a,b)
print(a+b)
coroutine.yield()
print(a-b)
end
co=coroutine.wrap(add)
co(1,5)
print("主程")
co()
--yield有参与resume,第一个参数是true/false
function add(a,b)
print(a)
coroutine.yield(a+b,a-b)
return a*b
end
cor=coroutine.create(add)
res1,res2,res3=coroutine.resume(cor,1,5)
print(res1,res2,res3)
print("主程resume")
res4,res5=coroutine.resume(cor)
print(res4,res5)
--status状态,suspended暂停的,running
function add(a,b)
print(coroutine.running())
print("2"..coroutine.status(co))
coroutine.yield(a+b,a-b)
return a*b
end
co=coroutine.create(add)
print("1"..coroutine.status(co))
coroutine.resume(co,2,3)
print("3"..coroutine.status(co))
print(coroutine.running())
coroutine.resume(co,2,3)
print("4"..coroutine.status(co))
--多次yield
function foo (a)
print("foo 函数输出", a)
return coroutine.yield(2 * a) -- 返回 2*a 的值
end
co = coroutine.create(function (a , b)
print("第一次协同程序执行输出", a, b) -- co-body 1 10
local r = foo(a + 1)
print("第二次协同程序执行输出", r)
local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入
print("第三次协同程序执行输出", r, s)
return b, "结束协同程序" -- b的值为第二次调用协同程序时传入
end)
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("---分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")
--]]
--[[IO 文件(有中文乱码问题)
--行读 r
file=io.open("file.txt","r")
io.input(file)
print(io.read())
print(io.read())
print(io.read())
print(io.read())
print(io.read())
print(io.read())
io.close(file)
--w,覆盖
--增,a 完全模式
file=io.open("file.txt","a")
io.output(file)
io.write("谁都想拥有情人完整的心")
io.close(file)
--全读,*a
file=io.open("file.txt","r")
io.input(file)
print(io.read("*a"))
io.close(file)
--字读 ,连着读
file=io.open("file.txt","r")
io.input(file)
print(io.read(10))
print(io.read(10))
io.close(file)
--完全模式
--]]
---[[垃圾回收
mytable = {"apple", "orange", "banana"}
print(collectgarbage("count"))
mytable = nil
print(collectgarbage("count"))
print(collectgarbage("collect"))--做一次完整的垃圾收集循环
print(collectgarbage("count"))
--]]
---[[面向对象
--person,通过 .
person={name="尚可云",age=18,eat=function()
print("eat()")
end}
person.eat()
--self
person={name="尚可云",age=18,eat=function(self)
print(self.name.."eat()")
end}
a=person
person=nil
a.eat(a)
--通过 :, 自动赋值 self, 读取也是 :
person={name="祖逖",age=18}
function person:eat()
print(self.name.."eat()")
end
a=person
a:eat()
--构造对象 == 实例
person={name="许靖"}
function person:eat()
print(self.name.."eat()")
end
function person:new()
local t={}
setmetatable(t,{__index=self})
return t
end
person1=person:new()
person1.name="高阜"
person1:eat()
-- == 多态
person={name="吴明彻"}
function person:eat()
print(self.name.."eat()")
end
function person:new(o)
t=o or {}
--setmetatable(t,{__index=self})
setmetatable(t,self)
self.__index=self
return t
end
person1=person:new( {sex="男"} )
print(person1.sex)
-- ==继承
person={name="岳飞"}
function person:eat()
print(self.name.."eat()")
end
function person:new()
local t={}
setmetatable(t,{__index=self})
return t
end
hero=person:new()
hero1=hero:new()
hero1.name="岳云"
hero1:eat()
--]]