You can write your topic however you want, but you need to answer these questions:
What do you want to achieve?
Smooth Tower animations.
What is the issue?
As you can see in the video. When the tower shoots it kinda breaks the animation of idle and overlaping it? For the first shot you can see the tower shoots then T-Pose and idle then again shoots. The real problem is for lower end pc’s my friend tested this on his laptop with 40fps avreage and the animations where just broken. Do you have an idea of what could help?
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I seached this problem quite a few times and i saw a problem about the animations status when you export it. Example: Idle ,Core ,Action etc. That did not work and i decided to add a cooldown and it just turned on a mess
local RepStorage = game:GetService("ReplicatedStorage")
local events = RepStorage:WaitForChild("Events")
local animateTower = events:WaitForChild("AnimateTower")
db = false
local function setAnim(object,animName)
local humanoid = object:WaitForChild("Humanoid")
local animationFolder = object:WaitForChild("Animations")
if humanoid and animationFolder then
local Animationobj = animationFolder:FindFirstChild(animName)
if Animationobj then
local animator = Instance.new("Animator", humanoid)
local playingTracks = animator:GetPlayingAnimationTracks()
for i,track in pairs(playingTracks) do
if track.Name == animName then
return track
end
end
local animtrack = animator:LoadAnimation(Animationobj)
return animtrack
end
end
end
local function playAnim(object,animName)
local animtrack = setAnim(object, animName)
print(object)
if animtrack then
if animName then
local humanoid = object:WaitForChild("Humanoid")
local animationFolder = object:WaitForChild("Animations")
local config = object:WaitForChild("Config")
local speed = config:FindFirstChild("Cooldown").Value
animtrack:Play()
end
else
warn("Something gone wrong")
end
end
workspace.Towers.ChildAdded:Connect(function(obj)
playAnim(obj,"Idle")
end)
animateTower.OnClientEvent:Connect(function(tower,animName)
for i,v in pairs(tower.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
tower.Shoot:Play()
playAnim(tower,animName)
task.wait(.8)
for i,v in pairs(tower.Humanoid:GetPlayingAnimationTracks()) do
v:Stop()
end
end)
Maybe the hitting animation needed a while to load? And about the animation overlapping, you could try stopping the other animation tracks that are playing. For example
Just keep the Idle animation continuously playing and set the priority via the script of the Shoot animation higher, you can do this when you use AnimationTrack:Play(.1, weight). So set the shoot animation’s weight to 2 and the idle to 1. Quick note if you change the FadeTime, it will either look smoother or will not show at all. Extending the animation would fix it.
P.S. Make the tower look at the nearest enemy, I suggest to use :Lerp(.5) to make it somewhat smooth. Have the paramater inside Lerp be anywhere from .1 to .9, this will make him move smoother if he looks at enemy 1 and then at enemy 2 if enemy 1 is too far away. If no enemies are nearby then just dont move him at all.
Uh yeah. It went good but i dont know what i did wrong or so but now its glitching out even more. Do you got another Solution to this?
Also here is the new code:
local RepStorage = game:GetService("ReplicatedStorage")
local events = RepStorage:WaitForChild("Events")
local animateTower = events:WaitForChild("AnimateTower")
db = false
local function changeWeight(animationTrack, weight, fadeTime)
animationTrack:AdjustWeight(weight, fadeTime)
local startTime = tick()
print("Time taken to change weight " .. tostring(tick() - startTime))
end
local function setAnim(object,animName)
local humanoid = object:WaitForChild("Humanoid")
local animationFolder = object:WaitForChild("Animations")
if humanoid and animationFolder then
local Animationobj = animationFolder:FindFirstChild(animName)
if Animationobj then
local animator = Instance.new("Animator", humanoid)
local playingTracks = animator:GetPlayingAnimationTracks()
for i,track in pairs(playingTracks) do
if track.Name == animName then
return track
end
end
local animtrack = animator:LoadAnimation(Animationobj)
return animtrack
end
end
end
local function playAnim(object,animName)
local animtrack = setAnim(object, animName)
print(object)
if animtrack then
if animName then
local humanoid = object:WaitForChild("Humanoid")
local animationFolder = object:WaitForChild("Animations")
local config = object:WaitForChild("Config")
local speed = config:FindFirstChild("Cooldown").Value
if animName == "Attack" then
changeWeight(animtrack,2,1)
animtrack:AdjustSpeed(speed)
animtrack:Play()
elseif animName == "Idle" then
changeWeight(animtrack,1,1)
animtrack:AdjustSpeed(speed)
animtrack:Play()
end
end
else
warn("Something gone wrong")
end
end
workspace.Towers.ChildAdded:Connect(function(obj)
playAnim(obj,"Idle")
end)
animateTower.OnClientEvent:Connect(function(tower,animName)
tower.Shoot:Play()
playAnim(tower,animName)
end)
i can try if you want, but i probably wont be helpful
maybe try stopping the idle, then beginning it again in a loop, but not an infinite loop, but a boolvalue loop
heres a script of what i mean:
while [boolvalue] do
--code here
end
it allows you to toggle off the bool, so it no longer loops, and then beginning the attack animation
affect the attack animation the same way so they both can be toggled
i assume you use some range system, so begin the attack animations if its in range while also turning off the idle BEFORE the attack, and vice versa when it goes out of range
There is no point into doing this. As with many other towers player will place it will break. So the current verison i have is the one to go with. And the attack animations is detected when the mobs are in a certain range.
This is the only part in my main script that the tower activates the animations
function FindNearestTarget(newTower)
local maxDistance = newTower.Config.Range.Value
local nearestTarget = nil
for i, target in ipairs(workspace.Mob:GetChildren()) do
local distance = (target.HumanoidRootPart.Position - newTower.HumanoidRootPart.Position).Magnitude
if distance < maxDistance then
nearestTarget = target
maxDistance = distance
end
end
return nearestTarget
end
function tower.Attack(newTower,player)
local target = FindNearestTarget(newTower)
if target and target:FindFirstChild("Humanoid") and target.Humanoid.Health > 0 then
local targetCframe = CFrame.lookAt(newTower.HumanoidRootPart.Position,target.HumanoidRootPart.Position)
newTower.HumanoidRootPart.CFrame = targetCframe
animateTower:FireAllClients(newTower,"Attack")
target.Humanoid:TakeDamage(newTower.Config.Damage.Value)
player.Cash.Value += newTower.Config.Damage.Value
task.wait(newTower.Config.Cooldown.Value)
end
task.wait(.8)
if newTower and newTower.Parent then
tower.Attack(newTower,player)
end
end