Here’s in the breakdown of an ability that spawns units and moves them with rotation, making use of the Physics library
The end result while there is no enemies to go to would be like this:
I include a Debug boolean that can be enabled to show the path and acquisition of different states:
The complete codes for the ability can be found in the following SpellLibrary links:
The entire lua file has comments for every decision. I hope it helps understand and adapt this skill to different behaviors.
I’ll just leave the lines related to physics here, special thanks to BMD for helping me through the entire process of rewriting this ability.
First step is to make each spawned unit a physics units and apply the properties.
Physics Readme to know what these do.
-- Make the spirit a physics unit Physics:Unit(unit) -- General properties unit:PreventDI(true) unit:SetAutoUnstuck(false) unit:SetNavCollisionType(PHYSICS_NAV_NOTHING) unit:FollowNavMesh(false) unit:SetPhysicsVelocityMax(spirit_speed) unit:SetPhysicsVelocity(spirit_speed * RandomVector(1)) unit:SetPhysicsFriction(0) unit:Hibernate(false) unit:SetGroundBehavior(PHYSICS_GROUND_LOCK)
After this, we want to control the units behavior on each frame, making use of the OnPhysicsFrame function.
-- This is set to repeat on each frame unit:OnPhysicsFrame(function(unit) -- Move the unit orientation to adjust the particle Unit:SetForwardVector( ( unit:GetPhysicsVelocity() ):Normalized() ) -- Movement and Collision detection are state independent -- MOVEMENT -- Get the direction local diff = point - unit:GetAbsOrigin() diff.z = 0 local direction = diff:Normalized() -- Calculate the angle difference local angle_difference = RotationDelta(VectorToAngles(unit:GetPhysicsVelocity():Normalized()), VectorToAngles(direction)).y -- Set the new velocity if math.abs(angle_difference) < 5 then -- CLAMP local newVel = unit:GetPhysicsVelocity():Length() * direction unit:SetPhysicsVelocity(newVel) elseif angle_difference > 0 then local newVel = RotatePosition(Vector(0,0,0), QAngle(0,10,0), unit:GetPhysicsVelocity()) unit:SetPhysicsVelocity(newVel) else local newVel = RotatePosition(Vector(0,0,0), QAngle(0,-10,0), unit:GetPhysicsVelocity()) unit:SetPhysicsVelocity(newVel) end -- COLLISION CHECK local distance = (point - current_position):Length() local collision = distance < 50 -- STATE DEPENDENT LOGIC -- Damage, Healing and Targeting are state dependent. -- Check the full script on SpellLibrary
Last is to stop the units, very simple with this: