Hello, I’m currently making a Tower Defense game and to handle the turns, I chose to tween orientation. I’ve already tried tweening CFrame, but because there already is a tween active on CFrame to determine the position, It did not work. Note:(I am exclusively tweening the Orientation on the client, as on the server, the orientation does not change). What I am trying to look for is a method that works on anchored rigs and does not override a previous tween on CFrame that is still running. The solution that I am looking for also needs a transition (not instantanous). Any help is appreciated!
This function is for tweening the orientation exclusively on the client.
local function Lookat(Enemy: Model, OldPos: Vector3, NewPos: Vector3, Speed: number, Delta: number, EnemyId: number, Point: number)
local PrimaryPart: BasePart = Enemy.PrimaryPart :: BasePart;
local CurrentPos: Vector3 = OldPos :: Vector3;
local NextPos: Vector3 = (WayPoints:FindFirstChild(tostring(Point+1)) :: BasePart).Position :: Vector3;
local ModelY = PrimaryPart.Position.Y
local At = Vector3.new(CurrentPos.X, ModelY, CurrentPos.Z)
local Lookat = Vector3.new(NextPos.X, ModelY, NextPos.Z)
local cframe = CFrame.lookAt(At, Lookat):ToObjectSpace(PrimaryPart.CFrame)
local x, y, z = cframe:ToEulerAnglesYXZ();
local oriX, oriY, oriZ = math.deg(x), math.deg(y), math.deg(z)
print(oriX, oriY, oriZ)
local orientation = Vector3.new(oriX, oriY, oriZ)
local function CheckTween()
local x, y, z = cframe:ToWorldSpace(PrimaryPart.CFrame):ToEulerAnglesXYZ()
return Vector3.new(math.rad(x), math.rad(y), math.rad(z))
end
local _TweenInfo = TweenInfo.new(Delta, Enum.EasingStyle.Linear, Enum.EasingDirection.In);
local Tween = TweenService:Create(PrimaryPart, _TweenInfo, {Orientation = CheckTween() });
local EnemyTweens = LocalStorage[EnemyId];
if not EnemyTweens then
return;
else
Tween:Play();
table.insert(EnemyTweens, Tween)
Tween.Completed:Once(function()
local TweenIndex = table.find(EnemyTweens, Tween)
if TweenIndex then
table.remove(EnemyTweens, TweenIndex)
end
end)
end
end
This connection below fires every one tenth of a second, and the function TweenPosition tweens the CFrame.
EnemySync.OnClientEvent:Connect(function(TotalPackage: {{EnemyId: number, Type: string, Health: number, OldPos: Vector3, NewPos: Vector3, Speed: number, LastPoint: number}}, Delta: number)
for _, Package in ipairs(TotalPackage) do
local CurrentEnemy: Model = nil;
local _Enemy = ClientEnemies:FindFirstChild(tostring(Package.EnemyId)) :: Model;
if _Enemy then
CurrentEnemy = _Enemy;
else
CurrentEnemy = EnemyStorage:WaitForChild(Package.Type):Clone() :: Model
if CurrentEnemy.PrimaryPart then
CurrentEnemy.PrimaryPart.CFrame = CFrame.new(Package.OldPos);
CurrentEnemy.Name = tostring(Package.EnemyId);
CurrentEnemy.Parent = ClientEnemies;
LocalStorage[Package.EnemyId] = {Tweens = {}, CheckPoint = 0};
else
CurrentEnemy:Destroy();
end
end
if Package.LastPoint ~= LocalStorage[Package.EnemyId].CheckPoint then
Lookat(CurrentEnemy, Package.OldPos, Package.NewPos, Package.Speed, Delta, Package.EnemyId, Package.LastPoint);
end
LocalStorage[Package.EnemyId].CheckPoint = Package.LastPoint;
TweenPosition(CurrentEnemy, Package.OldPos, Package.NewPos, Delta, Package.EnemyId);
end
end)