我們在制作Lua modifier的時候,第一步自然是這個API
LinkLuaModifier("modifier_your_modifier_name", "path/to/your/modifier/modifier_your_modifier_name.lua", LUA_MODIFIER_MOTION_NONE)
多思考一下就不難想到槐脏,最后一個參數(shù)喉童,是做什么用的,如果改為其他的結(jié)果顿天,比如LUA_MODIFIER_MOTION_HORIZONTAL/LUA_MODIFIER_MOTION_VERTICAL/LUA_MODIFIER_MOTION_BOTH堂氯,會有什么不同呢蔑担?
答案是,如果你在Lua modifier的代碼里面不做什么特殊的處理的話咽白,做出來的效果并沒有什么不同啤握。
而這個參數(shù)的不同,導致的結(jié)果是晶框,我們在modifier_your_modifier.lua中排抬,使用
modifier_your_modifier_name = class({})
所創(chuàng)建的這個class,在你為其指定LUA_MODIFIER_MOTION_HORIZONTAL
的時候授段,其鏈接到的class不是CDOTA_Modifier_Lua
畜埋,而是CDOTA_Modifier_Lua_Horizontal_Motion
,而仔細查看這個繼承自CDOTA_Modifier_Lua
的class的API文檔畴蒲,不難發(fā)現(xiàn)悠鞍,他多出來的幾個API就是實現(xiàn)運動控制的關(guān)鍵。
首先模燥,我們需要在modifier的OnCreated
函數(shù)中咖祭,調(diào)用ApplyHorizontalMotionController
,之后在UpdateHorizontalMotion
的函數(shù)中為單位刷新位置蔫骂,之后在modifier的OnDestroy
函數(shù)中為單位移除運動控制器RemoveHorizontalMotionController
么翰。
具體實現(xiàn)
modifier_horizontal_motion_example = class({})
function modifier_horizontal_motion_example:OnDestroy()
if IsServer() then
-- 移除運動控制器
self:GetParent():RemoveHorizontalMotionController(self)
end
end
function modifier_horizontal_motion_example:OnCreated(kv)
if IsServer() then
-- 為單位添加水平運動控制器
self:ApplyHorizontalMotionController()
local owner = self:GetParent()
-- 儲存一些初始狀態(tài)
self.vStartingPosition = owner:GetOrigin()
self.flTimeExpired = 0
end
end
function modifier_player_entering_next_level:UpdateHorizontalMotion(me, dt)
if IsServer() then
-- 計算具體的新位置,這個要根據(jù)實際需要來
-- me指代的是擁有運動控制器的單位辽旋,也就是這個modifier的owner浩嫌,dt就指距離上次調(diào)用這個
-- 函數(shù)過去的時間
-- 引擎將會為這兩次調(diào)用之間平滑地插補動畫
me:SetOrigin(newOrigin)
end
end
至于具體想要怎么動,那就看你想要具體怎么計算newOrigin
了补胚。
舉一個簡單的例子:
newOrigin = self:GetParent():GetForwardVector() * 1000 + self:GetParent():GetOrigin()
這樣這個單位就會以1000的速度向前沖刺了码耐。
如果你還要上上下下地動?
原理是一樣的溶其,你需要在OnCreated函數(shù)中添加 self:ApplyVerticalMotionController()
骚腥,并在UpdateVerticalMotion(me, dt)
中為單位確定新的位置。
需要注意的是瓶逃,你需要先獲取單位所在的位置束铭,然后計算單位的Z軸的位置,并使用me:SetOrigin()
來確定單位的位置厢绝。
function modifier_vertical_motion_example:UpdateVerticalMotion(me, dt)
if IsServer() then
local origin = me:GetOrigin()
origin.z = CalculateYourZ() -- 具體怎么計算根據(jù)你的實際需要來
me:SetOrigin(origin)
end
end
最后放上一段自己的代碼
具體的實現(xiàn)效果是契沫,完成一次向指定地點的,高度為4000的拋物線運動:
modifier_creature_pudge_jump = class({})
function modifier_creature_pudge_jump:IsStunDebuff()
return true
end
function modifier_creature_pudge_jump:IsHidden()
return true
end
function modifier_creature_pudge_jump:IsPurgable()
return false
end
function modifier_creature_pudge_jump:RemoveOnDeath()
return false
end
function modifier_creature_pudge_jump:OnCreated(kv)
if IsServer() then
if self:ApplyHorizontalMotionController() == false or self:ApplyVerticalMotionController() == false then
self:Destroy()
return
end
self.vStartPosition = GetGroundPosition( self:GetParent():GetOrigin(), self:GetParent() )
self.vTargetPosition = self:GetAbility():GetCursorPosition()
self.flDuration = 1.7
self.flHeight = 4000
self.vDirection = (self.vTargetPosition - self.vStartPosition):Normalized()
self.flDistance = (self.vTargetPosition - self.vStartPosition):Length2D()
self.flHorizontalSpeed = self.flDistance / self.flDuration
-- 創(chuàng)建開始的特效和音效
EmitSoundOnLocationWithCaster(self.vStartPosition, "Ability.TossThrow", self:GetParent())
end
end
function modifier_creature_pudge_jump:OnDestroy()
if IsServer() then
self:GetParent():RemoveHorizontalMotionController(self)
self:GetParent():RemoveVerticalMotionController(self)
end
end
function modifier_creature_pudge_jump:DeclareFunctions()
local funcs = {
MODIFIER_PROPERTY_OVERRIDE_ANIMATION,
}
return funcs
end
function modifier_creature_pudge_jump:CheckState()
local state = {
[MODIFIER_STATE_STUNNED] = true,
}
return state
end
function modifier_creature_pudge_jump:GetOverrideAnimation()
return ACT_DOTA_CAST_ABILITY_ROT
end
function modifier_creature_pudge_jump:UpdateHorizontalMotion(me, dt)
if IsServer() then
-- 根據(jù)速度昔汉,設(shè)置當前的位置
local vOldPosition = me:GetOrigin()
local vNewPos = vOldPosition + self.vDirection * self.flHorizontalSpeed * dt
vNewPos.z = 0
me:SetOrigin(vNewPos)
-- 判斷是否到達了終點
end
end
function modifier_creature_pudge_jump:UpdateVerticalMotion(me, dt)
if IsServer() then
local vOrigin = me:GetOrigin()
local vDistance = (vOrigin - self.vStartPosition):Length2D()
local vZ = - 4 * self.flHeight / (self.flDistance * self.flDistance) * (vDistance * vDistance) + 4 * self.flHeight / self.flDistance * vDistance
vOrigin.z = vZ
-- 判斷是否到達了終點
local flGroundHeight = GetGroundHeight( vOrigin, self:GetParent() )
local bLanded = false
if ( vOrigin.z < flGroundHeight and vDistance > self.flDistance / 2 ) then
vOrigin.z = flGroundHeight
bLanded = true
end
me:SetOrigin(vOrigin)
if bLanded == true then
-- ApplyDamage
local units = FindUnitsInRadius(self:GetParent():GetTeamNumber(), self:GetParent():GetOrigin(), nil, 275, DOTA_UNIT_TARGET_TEAM_BOTH, DOTA_UNIT_TARGET_ALL, DOTA_UNIT_TARGET_FLAG_NONE, FIND_ANY_ORDER, false)
for _, unit in pairs(units) do
DealDamage(self:GetParent(), unit, 1, self)
end
-- Particle
local pid = ParticleManager:CreateParticle("particles/econ/items/earthshaker/earthshaker_totem_ti6/earthshaker_totem_ti6_leap_impact.vpcf", PATTACH_WORLDORIGIN, self:GetParent())
ParticleManager:SetParticleControl(pid, 0, me:GetOrigin())
ParticleManager:ReleaseParticleIndex(pid)
EmitSoundOnLocationWithCaster(self:GetParent():GetOrigin(), "Ability.TossImpact", self:GetParent())
self:GetParent():RemoveHorizontalMotionController(self)
self:GetParent():RemoveVerticalMotionController(self)
self:SetDuration(0.15, true)
end
end
end
教程到此結(jié)束懈万。