想要怎么动,那就怎么动,用Lua modifier实现位移技能

我们在制作Lua modifier的时候,第一步自然是这个API

LinkLuaModifier("modifier_your_modifier_name", "path/to/your/modifier/modifier_your_modifier_name.lua", LUA_MODIFIER_MOTION_NONE)

多思考一下就不难想到,最后一个参数,是做什么用的,如果改为其他的结果,比如LUA_MODIFIER_MOTION_HORIZONTAL/LUA_MODIFIER_MOTION_VERTICAL/LUA_MODIFIER_MOTION_BOTH,会有什么不同呢?
答案是,如果你在Lua modifier的代码里面不做什么特殊的处理的话,做出来的效果并没有什么不同。
而这个参数的不同,导致的结果是,我们在modifier_your_modifier.lua中,使用

modifier_your_modifier_name = class({})

所创建的这个class,在你为其指定LUA_MODIFIER_MOTION_HORIZONTAL的时候,其链接到的class不是CDOTA_Modifier_Lua,而是CDOTA_Modifier_Lua_Horizontal_Motion,而仔细查看这个继承自CDOTA_Modifier_Lua的class的API文档,不难发现,他多出来的几个API就是实现运动控制的关键。
首先,我们需要在modifier的OnCreated函数中,调用ApplyHorizontalMotionController,之后在UpdateHorizontalMotion的函数中为单位刷新位置,之后在modifier的OnDestroy函数中为单位移除运动控制器RemoveHorizontalMotionController
具体实现

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()
        -- 储存一些初始状态
        self.vStartingPosition                 = owner:GetOrigin()
        self.flTimeExpired                     = 0
    end
end

function modifier_player_entering_next_level:UpdateHorizontalMotion(me, dt)
    if IsServer() then
        -- 计算具体的新位置,这个要根据实际需要来
        -- me指代的是拥有运动控制器的单位,也就是这个modifier的owner,dt就指距离上次调用这个
        -- 函数过去的时间
        -- 引擎将会为这两次调用之间平滑地插补动画
        me:SetOrigin(newOrigin)
    end
end

至于具体想要怎么动,那就看你想要具体怎么计算newOrigin了。

举一个简单的例子:

newOrigin = self:GetParent():GetForwardVector() * 1000 + self:GetParent():GetOrigin()

这样这个单位就会以1000的速度向前冲刺了。

如果你还要上上下下地动?
原理是一样的,你需要在OnCreated函数中添加 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() -- 具体怎么计算根据你的实际需要来
        me:SetOrigin(origin)
    end
end

最后放上一段自己的代码
具体的实现效果是,完成一次向指定地点的,高度为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

        -- 创建开始的特效和音效
        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
        -- 根据速度,设置当前的位置
        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

教程到此结束。

你可能感兴趣的:(想要怎么动,那就怎么动,用Lua modifier实现位移技能)