流星

流星消逝的时候,光明已在望。黑暗无论多么长,光明迟早总是会来的。

一线天关卡脚本转为slua 有更新!

    2018/2/14
    在新版本里,已经决定不要在战斗中使用slua脚本
    因为一个场景里有最多16个人物角色,各种关卡道具,和道具刷新点以及可破坏物件等,全部用脚本来每一帧刷新会严重的降低帧率(但是原作是C++和pscript的架构不一样)
    所以以下文章意义不大,可以不用浪费时间了。
    unity里引入脚本,还是单纯的调用一下接口好了,比如UI/刷物品
    不要试图在战斗部分使用脚本(就是不要每帧update),这个性能损失得不偿失

    这篇日志只是还原一下原版本里的sn03关卡里,拒马和落石,以及开门的机关等的处理
    落石是受击后播放动画滚动到悬崖下,然后碎裂,同时播放音效,落石动画时还带有攻击盒,可以攻击任意人物角色
    拒马是一个长木栅栏,他背后有一个隐形的阻碍盒阻挡了角色的前进,当角色击打拒马时,拒马会随着血量的减少,播放不同的几个状态下的受击动画,当拒马的血量小于0时,会播放碎裂动画,同时把隐形的盒子取消激活SetActive(false)
    当碎裂动画结束时,其被SetActive(false),这样角色就能够继续前进
    开门机关,类似一个模型按钮,当受击时,他会使门播放开门动画,并且停留在最后一帧,而门在OnIdle里会判断,距离开门时刻有多久了,超过了设定的关门时间,门就会播放关门动画。

    以下脚本是从原版里改为slua后的脚本
    sn03.pst=>sn03.txt
    关卡剧本sn03-.pst还没有改
    这个脚本主要负责一线天关卡里的(关口尖刺)(拒马(木栅栏))(滚石)而其他的瓶子罐子,还有武器盒子,buff盒子我都注释掉了
    尖刺通过加载关卡des文件时,里面有custom{ name=damage100}之类的来设置伤害值
    SetSceneItem(name, “attribute”, “damage”, 1);是设置其能够攻击游戏阵营角色
    SetSceneItem(name, “name”, “machine”, 1);是设置其不要上下移动并绕Y轴旋转
    SetSceneItem(“D_ADoor01”, “attribute”, “collision”, 1);可以与角色碰撞,即角色不能穿越
    SetSceneItem(“D_ADoor01”, “attribute”, “damagevalue”, g_iLevel03DoorDamage);设置道具如果可以攻击角色,那么每次打角色多少血
    SetSceneItem(“D_Abutton01”, “pose”, 0, 0);播放0编号动作,不循环

    这个脚本需要引用main脚本里定义的一些公共函数,公共函数在main脚本里调用到原生c#类 这里main里引用了U3D类,调用这个类的静态函数提供脚本的具体实现
    main.txt脚本

    --脚本全局常量
    --item parameters for each level
    --小箱子HP
    g_iBoxMaxHP = 100;	
    --大箱子HP
    g_iBBoxMaxHP = 200;
    --椅子HP
    g_iChairMaxHP = 100;
    --桌子HP
    g_iDeskMaxHP = 150;
    --水罐HP
    g_iJugMaxHP = 100;
    --拒马HP
    g_iGiMaMaxHP = 3000;
    -- special parameter for each level
    g_iLevel01StoneMaxHP = 500;
    g_iLevel03DoorWaitTime = 7000;
    g_iLevel03GiMaMaxHP = 3000;
    g_iLevel03StoneDamage = 300;
    g_iLevel03DoorDamage = 50;
    g_iLevel04GiMaMaxHP = 10000;
    g_iLevel07KnifeDamage = 300;
    g_iLevel07PinDamage = 200;
    g_iLevel08StickDamage = 300;
    g_iLevel09StepTime = 1000;
    g_iLevel11DoorMaxHP = 10000;
    g_iLevel12StoveHP = 5000;
    g_iLevel13BridgeHP = 4000;
    
    function main()
    end
    
    function load()
    end
    
    function save()
    U3D.SaveClean()
    --U3D.SaveState("answer", answer)
    --U3D.SaveState("getreward", getreward)
    --U3D.SaveState("npcId", npcId)
    --U3D.SaveState("chufu_npc_talk", chufu_npc_talk)
    U3D.SaveDone()
    end
    
    function SetSceneItem(a, b, c, d)
    	U3D.SetSceneItem(a, b, c, d)
    end
    
    function MakeString(b, c)
    	str = string.format("%02d",c)
    	return (b..str)
    end
    
    function GetSceneItem(a, b)
    	return U3D.GetSceneItem(a, b)
    end
    
    function GetTeam(a)
    	return U3D.GetTeam(a)--得到角色属于流星或者蝴蝶
    end
    
    function Output(a)
    	print(a)
    end
    
    function NetEvent(a)
    	U3D.NetEvent(a)
    end
    
    function CreateEffect(a, b)
    	U3D.CreateEffect(a, b)
    end
    
    ///////////////////////////////////////main脚本结束//////////////////////////////////////
    
    关卡sn03.txt(原版里sn03.pst)
    local g_bStone01Active;
    local g_bStone02Active;
    
    local g_iADoor02OpenTime;
    local g_iBDoor01OpenTime;
    local g_iDoorWaitTime = 7000;
    
    local g_iPdoorMaxHP = 2000;
    local g_iPdoorState1HP;
    local g_iPdoorState2HP;
    local g_iPdoorState3HP;
    local g_iPdoorState4HP;
    local g_iPdoorState5HP;
    
    local g_bAPdoorAlive;
    local g_iAPdoorState;
    local g_iAPdoorShakePose;
    local g_iAPdoorHP;
    
    local g_bBPdoorAlive;
    local g_iBPdoorState;
    local g_iBPdoorShakePose;
    local g_iBPdoorHP;
    
    local function Scene_OnLoad()
    	local i;
    	local name;
    	
    	g_iDoorWaitTime = g_iLevel03DoorWaitTime;
    	g_iPdoorMaxHP = g_iLevel03GiMaMaxHP;
    	
    	g_iPdoorState1HP = (g_iPdoorMaxHP*3)/4;
    	g_iPdoorState2HP = (g_iPdoorMaxHP*2)/4;
    	g_iPdoorState3HP = (g_iPdoorMaxHP*1)/4;
    	g_iPdoorState4HP = 0;
    
    	SetSceneItem("D_ston01", "name", "machine", 1);
    	SetSceneItem("D_ston02", "name", "machine", 1);
    
    	for i=1,10 do
    		name = MakeString("D_sn03t", i);
    		SetSceneItem(name, "name", "machine", 1);
    		SetSceneItem(name, "attribute", "damage", 1);
    	end
    	
    	SetSceneItem("D_Abutton01", "name", "machine", 1);
    	SetSceneItem("D_Abutton02", "name", "machine", 1);
    	SetSceneItem("D_ADoor01", "name", "machine", 1);
    	SetSceneItem("D_ADoor01", "attribute", "collision", 1);
    	SetSceneItem("D_ADoor01", "attribute", "damagevalue", g_iLevel03DoorDamage);
    	SetSceneItem("D_ADoor01", "attribute", "damage", 1);
    
    	SetSceneItem("D_Bbutton01", "name", "machine", 1);
    	SetSceneItem("D_Bbutton02", "name", "machine", 1);
    	SetSceneItem("D_BDoor01", "name", "machine", 1);
    	SetSceneItem("D_BDoor01", "attribute", "collision", 1);
    	SetSceneItem("D_BDoor01", "attribute", "damagevalue", g_iLevel03DoorDamage);
    	SetSceneItem("D_BDoor01", "attribute", "damage", 1);
    
    	SetSceneItem("D_APdoor01", "name", "machine", 1);
    	SetSceneItem("D_APdoor01", "attribute", "damagevalue", 20);
    	
    	SetSceneItem("D_BPdoor01", "name", "machine", 1);
    	SetSceneItem("D_BPdoor01", "attribute", "damagevalue", 20);
    
    	SetSceneItem("D_APd02Box01", "name", "machine", 1);
    	SetSceneItem("D_BPd02Box01", "name", "machine", 1);
    end
    
    local function Scene_OnInit()
    	g_bStone01Active = 1;
    	g_bStone02Active = 1;
    
    	SetSceneItem("D_ston01", "pose", 0, 0);
    	SetSceneItem("D_ston01", "attribute", "active", 1);
    	SetSceneItem("D_ston01", "attribute", "collision", 1);
    	SetSceneItem("D_ston01", "attribute", "damage", 0);
    	SetSceneItem("D_ston01", "attribute", "damagevalue", g_iLevel03StoneDamage);
    	
    	SetSceneItem("D_ston02", "pose", 0, 0);
    	SetSceneItem("D_ston02", "attribute", "active", 1);
    	SetSceneItem("D_ston02", "attribute", "collision", 1);
    	SetSceneItem("D_ston02", "attribute", "damage", 0);
    	SetSceneItem("D_ston02", "attribute", "damagevalue", g_iLevel03StoneDamage);
    	
    	SetSceneItem("D_Abutton01", "pose", 0, 0);
    	SetSceneItem("D_Abutton02", "pose", 0, 0);
    	SetSceneItem("D_ADoor01", "pose", 0, 0);
    	
    	SetSceneItem("D_Bbutton01", "pose", 0, 0);
    	SetSceneItem("D_Bbutton02", "pose", 0, 0);
    	SetSceneItem("D_BDoor01", "pose", 0, 0);
    
    	SetSceneItem("D_APdoor01", "pose", 0, 0);
    	SetSceneItem("D_APdoor01", "attribute", "collision", 0);
    	SetSceneItem("D_APdoor01", "attribute", "damage", 0);
    	SetSceneItem("D_APd02Box01", "attribute", "collision", 1);
    	
    	SetSceneItem("D_BPdoor01", "pose", 0, 0);
    	SetSceneItem("D_BPdoor01", "attribute", "collision", 0);
    	SetSceneItem("D_BPdoor01", "attribute", "damage", 0);
    	SetSceneItem("D_BPd02Box01", "attribute", "collision", 1);
    
    	g_iAPdoorHP = g_iPdoorMaxHP;
    	g_bAPdoorAlive = 1;
    	g_iAPdoorState = 1;
    	g_iAPdoorShakePose = 1;
    	
    	g_iBPdoorHP = g_iPdoorMaxHP;
    	g_bBPdoorAlive = 1;
    	g_iBPdoorState = 1;
    	g_iBPdoorShakePose = 1;
    
    	--InitBoxes(g_iNumBoxes);
    	--InitBBoxs(g_iNumBBoxes);//函数名不对,可能是原版就有BUG 应该是InitBBoxes
    	--InitChairs(g_iNumChairs);
    	--InitDeskes(g_iNumDeskes);
    	--InitJugs(g_iNumJugs);
    end
    
    function D_APdoor01_OnAttack(id, character, damage)
    	if (GetTeam(character) ==1) then
    		return 0;
    	end
    	
    	local state;
    
    	g_iAPdoorHP = g_iAPdoorHP - damage;
    	
    	if ( g_iAPdoorState==1 and g_iAPdoorHP < g_iPdoorState1HP ) then
    	
    		g_iAPdoorState = g_iAPdoorState + 1;
    		g_iAPdoorShakePose = 3;
    		NetEvent(1);
    		SetSceneItem(id, "pose", 2, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iAPdoorState==2 and g_iAPdoorHP < g_iPdoorState2HP ) then
    		g_iAPdoorState = g_iAPdoorState  + 1;
    		g_iAPdoorShakePose = 5;
    		NetEvent(1);
    		SetSceneItem(id, "pose", 4, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iAPdoorState==3 and g_iAPdoorHP < g_iPdoorState3HP ) then
    	
    		g_iAPdoorState = g_iAPdoorState + 1;
    		g_iAPdoorShakePose = 7;
    		NetEvent(1);
    		SetSceneItem(id, "pose", 6, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iAPdoorState==4 and g_iAPdoorHP < 0 ) then
    	
    		g_iAPdoorState = g_iAPdoorState + 1;
    		NetEvent(1);
    		CreateEffect(id, "GiMaBRK");
    		SetSceneItem(id, "attribute", "interactive", 0);
    		SetSceneItem(id, "attribute", "collision", 0);
    		SetSceneItem(id, "pose", 8, 0);
    		SetSceneItem("D_APd02Box01", "attribute", "active", 0);
    		NetEvent(0);
    	end
    
    	state = GetSceneItem(id, "state");
    	if ( state==3 ) then
    		NetEvent(1);
    		CreateEffect(id, "GiMaHIT");
    		SetSceneItem(id, "pose", g_iAPdoorShakePose, 0);
    		NetEvent(0);
    	end
    end
    
    function D_APdoor01_OnIdle(id)
    	if ( g_iAPdoorState==5 and g_bAPdoorAlive==1 ) then
    		local pose;
    		pose = GetSceneItem(id, "pose");
    		if (pose ~= 8 ) then
    			return 0;
    		end
    		local state;
    		state = GetSceneItem(id, "state");
    		if ( state==3 ) then
    			g_bAPdoorAlive = 0;
    			NetEvent(1);
    			SetSceneItem("D_APdoor01", "attribute", "active", 0);
    			NetEvent(0);
    		end
    	end
    end
    
    function D_BPdoor01_OnAttack(id, character, damage)
    	if ( GetTeam(character)==2 ) then
    		return 0;
    	end
    	
    	local state;
    
    	g_iBPdoorHP = g_iBPdoorHP - damage;
    	
    	if ( g_iBPdoorState==1 and g_iBPdoorHP < g_iPdoorState1HP ) then
    		g_iBPdoorState = g_iBPdoorState + 1;
    		g_iBPdoorShakePose = 3;
    		NetEvent(1);
    		SetSceneItem(id, "pose", 2, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iBPdoorState==2 and g_iBPdoorHP < g_iPdoorState2HP ) then
    		g_iBPdoorState = g_iBPdoorState + 1;
    		g_iBPdoorShakePose = 5;
    		Output("Change State 3");
    		NetEvent(1);
    		SetSceneItem(id, "pose", 4, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iBPdoorState==3 and g_iBPdoorHP< g_iPdoorState3HP ) then
    		g_iBPdoorState = g_iBPdoorState + 1;
    		g_iBPdoorShakePose = 7;
    		Output("Change State 4");
    		NetEvent(1);
    		SetSceneItem(id, "pose", 6, 0);
    		NetEvent(0);
    	end
    	
    	if ( g_iBPdoorState==4 and g_iBPdoorHP < g_iPdoorState4HP ) then
    		g_iBPdoorState = g_iBPdoorState + 1;
    		NetEvent(1);
    		CreateEffect(id, "GiMaBRK");
    		SetSceneItem(id, "attribute", "interactive", 0);
    		SetSceneItem(id, "attribute", "collision", 0);
    		SetSceneItem(id, "pose", 8, 0);
    		SetSceneItem("D_BPd02Box01", "attribute", "active", 0);
    		NetEvent(0);
    	end
    
    	state = GetSceneItem(id, "state");
    	if ( state==3 ) then
    		NetEvent(1);
    		CreateEffect(id, "GiMaHIT");
    		SetSceneItem(id, "pose", g_iBPdoorShakePose, 0);
    		NetEvent(0);
    	end
    end
    
    function D_BPdoor01_OnIdle(id)
    	if ( g_iBPdoorState==5 and g_bBPdoorAlive==1 ) then
    		local pose = GetSceneItem(id, "pose");
    		if ( pose~=8 ) then
    			return 0;
    		end
    		local state;
    		state = GetSceneItem(id, "state");
    		if ( state==3 ) then
    			g_bBPdoorAlive = 0;
    			NetEvent(1);
    			SetSceneItem("D_BPdoor01", "attribute", "active", 0);
    			NetEvent(0);
    		end
    	end
    end
    
    function D_ston01_OnAttack(id, character, damage)
    	local pose = GetSceneItem(id, "pose");
    	if ( pose==1 ) then
    		return 0;
    	end
    
    	NetEvent(1);
    	CreateEffect(id, "StoneFIL");
    	CreateEffect("D_Sston01", "StoneFIL");
    	SetSceneItem(id, "pose", 1, 0);
    	SetSceneItem(id, "attribute", "collision", 0);
    	SetSceneItem(id, "attribute", "damage", 1);
    	NetEvent(0);
    end
    
    function D_ston01_OnIdle(id)
    	if ( g_bStone01Active==1 ) then
    		local pose = GetSceneItem(id, "pose");
    		if ( pose==0 ) then
    			return 0;
    		end
    		local state = GetSceneItem(id, "state");
    		if ( state==3 ) then
    			g_bStone01Active=0;
    			NetEvent(1);
    			SetSceneItem(id, "attribute", "active", 0);
    			NetEvent(0);
    		end
    	end
    end
    
    function D_ston02_OnAttack(id, character, damage)
    	local pose = GetSceneItem(id, "pose");
    	if ( pose==1 ) then
    		return 0;
    	end
    	
    	NetEvent(1);
    	CreateEffect(id, "StoneFIL");
    	CreateEffect("D_Sston02", "StoneFIL");
    	SetSceneItem(id, "pose", 1, 0);
    	SetSceneItem(id, "attribute", "collision", 0);
    	SetSceneItem(id, "attribute", "damage", 1);
    	NetEvent(0);
    end
    
    function D_ston02_OnIdle(id)
    	if ( g_bStone02Active==1 ) then
    		local pose = GetSceneItem(id, "pose");
    		if ( pose==0 ) then
    			return 0;
    		end
    		local state = GetSceneItem(id, "state");
    		if ( state==3 ) then
    			g_bStone02Active = 0;
    			NetEvent(1);
    			SetSceneItem(id, "attribute", "active", 0);
    			NetEvent(0);
    		end
    	end
    end
    
    function D_Abutton01_OnAttack(id, character, damage)
    	local pose = GetSceneItem("D_ADoor01", "pose");
    	if ( pose~=0 ) then
    		return 0;
    	end
    	g_iADoor02OpenTime = Misc("gettime");
    	NetEvent(1);
    	SetSceneItem("D_ADoor01", "pose", 1, 0);
    	SetSceneItem(id, "pose", 1, 0);
    	NetEvent(0);
    end
    
    function D_Abutton02_OnAttack(id, character, damage)
    	local pose = GetSceneItem("D_ADoor01", "pose");
    	if ( pose~=0 ) then
    		return 0;
    	end
    	g_iADoor02OpenTime = Misc("gettime");
    	NetEvent(1);
    	SetSceneItem("D_ADoor01", "pose", 1, 0);
    	SetSceneItem(id, "pose", 1, 0);
    	NetEvent(0);
    end
    
    function D_ADoor01_OnIdle(id)
    	local pose = GetSceneItem(id, "pose");
    	if ( pose==0 ) then
    		return 0;
    	end
    	local state = GetSceneItem(id, "state");
    	if ( pose==1 and state==3 ) then
    		local diff = Misc("gettime") - g_iADoor02OpenTime;
    		if ( diff > g_iDoorWaitTime ) then
    			Output("Close Door");
    			NetEvent(1);
    			SetSceneItem(id, "pose", 2, 0);
    			NetEvent(0);
    		end
    		return 1;
    	end
    	if ( pose==2 and state==3 ) then
    		NetEvent(1);
    		SetSceneItem(id, "pose", 0, 0);
    		NetEvent(0);
    		return 1;
    	end
    end
    
    function D_Bbutton01_OnAttack(id, character, damage)
    	local pose = GetSceneItem("D_BDoor01", "pose");
    	if ( pose~=0 ) then
    		return 0;
    	end
    	g_iBDoor01OpenTime = Misc("gettime");
    	NetEvent(1);
    	SetSceneItem("D_BDoor01", "pose", 1, 0);
    	SetSceneItem(id, "pose", 1, 0);
    	NetEvent(0);
    end
    
    function D_Bbutton02_OnAttack(id, character, damage)
    	local pose = GetSceneItem("D_BDoor01", "pose");
    	if ( pose~=0 ) then
    		return 0;
    	end
    	g_iBDoor01OpenTime = Misc("gettime");
    	NetEvent(1);
    	SetSceneItem("D_BDoor01", "pose", 1, 0);
    	SetSceneItem(id, "pose", 1, 0);
    	NetEvent(0);
    end
    
    function D_BDoor01_OnIdle(id)
    	local pose = GetSceneItem(id, "pose");
    	if ( pose==0 ) then
    		return 0;
    	end
    	local state = GetSceneItem(id, "state");
    	if ( pose==1 and state==3 ) then
    		local diff = Misc("gettime") - g_iBDoor01OpenTime;
    		if ( diff > g_iDoorWaitTime ) then
    			Output("Close Door");
    			NetEvent(1);
    			SetSceneItem(id, "pose", 2, 0);
    			NetEvent(0);
    		end
    	end
    	if ( pose==2 and state==3 ) then
    		NetEvent(1);
    		SetSceneItem("D_BDoor01", "pose", 0, 0);
    		NetEvent(0);
    	end
    	end
    
    function main()
    	Scene_OnLoad()
    	Scene_OnInit()
    end
    

    分析下物件的处理代码,物件主要有受击消息,和Idle消息
    看下石头的受击消息处理

    function D_ston01_OnAttack(id, character, damage)
    	local pose = GetSceneItem(id, "pose");取得石头当前动画编号,这个是fmc文件里的
    	if ( pose==1 ) then当播放1编号动画时,1是石头从山顶落到地面,这种情况下,石头应该是无法受击的,但是他这里写了
    		return 0;
    	end
    
    	NetEvent(1);网络同步开始
    	CreateEffect(id, "StoneFIL");在石头上创建一个特效StoneFil.ef
    	CreateEffect("D_Sston01", "StoneFIL");在地面挂载点D_Sston01上创建一个特效,这个特效就是石头炸开的声音
    	SetSceneItem(id, "pose", 1, 0);让石头播放1号动画,不循环
    	SetSceneItem(id, "attribute", "collision", 0);//让场景角色可以穿越石头
    	SetSceneItem(id, "attribute", "damage", 1);让石头拥有攻击能力,他的攻击力在 des文件里有设定
    	NetEvent(0);网络同步结束
    end
    

    看石头在Idle时候的处理

    function D_ston01_OnIdle(id)
    	if ( g_bStone01Active==1 ) then 如果还是激活的
    		local pose = GetSceneItem(id, "pose");取得动画id
    		if ( pose==0 ) then 动画id为0,返回
    			return 0;
    		end
    		local state = GetSceneItem(id, "state");取得动画状态
    		if ( state==3 ) then 如果是播放到末尾帧停止了
    			g_bStone01Active=0; 脚本内设置变量标识其为非激活
    			NetEvent(1);网络同步开始
    			SetSceneItem(id, "attribute", "active", 0);设置石头激活为 false
    			NetEvent(0);网络同步结束
    		end
    	end
    end
    

    可以看到,这个石头没有HP,仅仅受击就播放动画,播放特效,动画播放完了播放状态就变化为3,然后在其对应的Update里调用这个Idle消息,他就会把自己SetActive(false),这样脚本控制起来非常灵活,但是要很细致的用脚本控制所有细节

    然后看下拒马的消息处理

    function D_BPdoor01_OnAttack(id, character, damage)
    	if ( GetTeam(character)==2 ) then 如果打击场景物件的角色属于蝴蝶阵营
    		return 0;直接返回,过滤了蝴蝶阵营打拒马的情况
    	end
    	
    	local state;
    
    	g_iBPdoorHP = g_iBPdoorHP - damage;更新气血
    	
    	if ( g_iBPdoorState==1 and g_iBPdoorHP < g_iPdoorState1HP ) then 如果状态为1,且气血小与3/4时
    		g_iBPdoorState = g_iBPdoorState + 1;切换到下个状态 状态+1
    		g_iBPdoorShakePose = 3; 受击动画为3
    		NetEvent(1);同步开始
    		SetSceneItem(id, "pose", 2, 0);播放动画2
    		NetEvent(0);同步结束
    	end
    	
    	if ( g_iBPdoorState==2 and g_iBPdoorHP < g_iPdoorState2HP ) then 途观状态为2,切气血小与2/4时
    		g_iBPdoorState = g_iBPdoorState + 1;再切换到下个状态
    		g_iBPdoorShakePose = 5;受击动画为5
    		Output("Change State 3");
    		NetEvent(1);
    		SetSceneItem(id, "pose", 4, 0);播放4号动画
    		NetEvent(0);
    	end
    	
    	if ( g_iBPdoorState==3 and g_iBPdoorHP< g_iPdoorState3HP ) then 如果状态为3 且血量小与1/4时
    		g_iBPdoorState = g_iBPdoorState + 1; 切换状态+1
    		g_iBPdoorShakePose = 7;受击抖动动画为7
    		Output("Change State 4");
    		NetEvent(1);
    		SetSceneItem(id, "pose", 6, 0);播放6号动画
    		NetEvent(0);
    	end
    	
    	if ( g_iBPdoorState==4 and g_iBPdoorHP < g_iPdoorState4HP ) then 如果状态为4,切气血小于0时
    		g_iBPdoorState = g_iBPdoorState + 1;切换状态
    		NetEvent(1);
    		CreateEffect(id, "GiMaBRK");在拒马上播放特效
    		SetSceneItem(id, "attribute", "interactive", 0);设置拒马不能与其他角色交互,这句意思还不明显
    		SetSceneItem(id, "attribute", "collision", 0);设置拒马能与角色互相穿透
    		SetSceneItem(id, "pose", 8, 0);播放动画8
    		SetSceneItem("D_BPd02Box01", "attribute", "active", 0);把隐形的阻碍物件 SetActive(false),就相当于开门了。
    		NetEvent(0);
    	end
    
    	state = GetSceneItem(id, "state"); 取得动画播放状态
    	if ( state==3 ) then 如果动画播放完毕
    		NetEvent(1);
    		CreateEffect(id, "GiMaHIT");在拒马上创建特效
    		SetSceneItem(id, "pose", g_iBPdoorShakePose, 0);播放受击抖动动画
    		NetEvent(0);
    	end
    end
    

    看下Idle函数

    function D_BPdoor01_OnIdle(id)
    	if ( g_iBPdoorState==5 and g_bBPdoorAlive==1 ) then 如果状态为5,且还处于激活
    		local pose = GetSceneItem(id, "pose"); 得到当前动画ID
    		if ( pose~=8 ) then 如果是动画8,则返回,不处理
    			return 0;
    		end
    		local state;
    		state = GetSceneItem(id, "state");得到动画播放状态
    		if ( state==3 ) then 如果动画播放完毕
    			g_bBPdoorAlive = 0; 取消激活
    			NetEvent(1);
    			SetSceneItem("D_BPdoor01", "attribute", "active", 0);设置游戏对象SetActive(false)
    			NetEvent(0);
    		end
    	end
    end
    

    这个拒马如果不用脚本来处理,真的很麻烦,光配置数据要实现这种 (血量处于某个范围对应某个受击动画这种,要配的数据估计不少),而且这完全是个特例,基本上原版里很少见这样用的

    看到后面的 秦皇陵,里面摆动的斧头,还有岩浆下往上冒的石柱,都是通过脚本与角色交互的。

    这里的机关按钮,还没研究清楚,他的des文件里,有些参数猜不出意思
    他的摇杆部分,这个摇杆还不清楚为啥没设置可受击就跑到消息处理了,照我的想法最少先告诉我这个摇杆可受攻击,然后才会调用碰撞检测,再进入受击消息处理。
    Object objon
    {
    Position: 0.379 0.007 -0.878
    Quaternion: -0.991 0.001 0.131 0.004
    TextureAnimation: 0 0.000 0.000
    Custom:
    {
    motionanimation=0;
    onClick=3;
    IExtparam1=100;
    pose0=0,70;
    }
    }
    底座部分
    Object sobseat01
    {
    Position: 0.002 0.615 -0.878
    Quaternion: -1.000 0.000 0.000 0.004
    TextureAnimation: 0 0.000 0.000
    Custom:
    {
    }
    }

    开门机关处理函数

    function D_Bbutton01_OnAttack(id, character, damage)
    	local pose = GetSceneItem("D_BDoor01", "pose");q取得大门的动画ID
    	if ( pose~=0 ) then 如果大门的动画ID不是0则返回,也就是当大门处于开启和关闭的动画时,攻击这个机关是没起作用的
    		return 0;
    	end
    	g_iBDoor01OpenTime = Misc("gettime");得到当前游戏时间,记录开门的时刻
    	NetEvent(1);
    	SetSceneItem("D_BDoor01", "pose", 1, 0);使大门播放开启动画
    	SetSceneItem(id, "pose", 1, 0);自己播放1号动画,也就是摇杆的拉动动画
    	NetEvent(0);
    end
    

    看下大门的处理OnIdle

    function D_BDoor01_OnIdle(id)
    	local pose = GetSceneItem(id, "pose");取得当前动作编号
    	if ( pose==0 ) then 如果是0号动画,返回
    		return 0;
    	end
    	local state = GetSceneItem(id, "state")取得动画状态,3代表动画播放完毕停留在最后一帧;
    	if ( pose==1 and state==3 ) then 如果动作是开门,且停留在最后一帧
    		local diff = Misc("gettime") - g_iBDoor01OpenTime; 用当前游戏时间减去开门时刻的时间
    		if ( diff > g_iDoorWaitTime ) then 如果 间隔时间大于 等待关门时间
    			Output("Close Door");
    			NetEvent(1);
    			SetSceneItem(id, "pose", 2, 0);播放2号动画,关门
    			NetEvent(0);
    		end
    	end
    	if ( pose==2 and state==3 ) then 如果是2号动画,且播放完毕了
    		NetEvent(1);
    		SetSceneItem("D_BDoor01", "pose", 0, 0); 设置播放0号动画,0号动画为待机动画,就是第一帧
    		NetEvent(0);
    	end
    	end
    
    validate