想要怎么动,那就怎么动,用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

教程到此结束。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容