Hi, so i’ve made an expression system for my character. It is a modulescript that has two functions: MouthFaceCamera()
and Swap(Eyebrows, Eyes, Mouth, Expression)
. Let me just say that MouthFaceCam()
isn’t really important, we’ll be largely focusing on Swap()
.
The Swap()
simply takes 4 arguments that are all strings. Eyebrows for the type of Eyebrow, Eyes for the type of Eyes, and Mouth for the type of Mouth. The last argument, “Expression”, is simply just the name of the Expression. So, for example, Swap("Happy", "Happy", "HappyClosed", "Idle")
will change the Eyebrows, Eyes, Mouth and set the Expression’s name to “Idle”. Now, what this does is it sets the Expression
attribute of the Settings
Configuration in the Player himself to “Idle”. Simple enough, right?
Well, it does work. For the most part. Everything runs smoothly, the mouth always faces the camera, etc. But there is one issue that i just can’t solve at all. The Fall animation/expression. Simply put, whenever the CurrentAnimation is the default “fall” animation with a priority of “Core” and a weight of 10 (just like all the other default animations), the fall expression will always override the other ones for some reason. So, for example, if the current animation is “Ring”, then the “Fall” expression will either override the Ring expression completely and not even let it appear, or just interrupt it completely before the animation is even finished.
I do not know why this keeps happening? The fall animation’s priority is very well set to “Core”, and it’s weight is just 10. Meanwhile, the other animations (aside from idle, walk & run) are all set to Action4, and even if i change their weight to be infinitely bigger than the fall animation’s, it just won’t work. I’ve tried asking the A.I assistant and looking around the DevForum for help, nothing. Here’s the code and a video showcasing the problem :
- Local Script that requires the “Expressions” module and uses it to swap the expressions based on the animation playing:
--|Animation Checker
local Check
local CurrentAnim
Check = RunService.Heartbeat:Connect(function()
if not Character:FindFirstChild("Humanoid") or Humanoid.Health == 0 then
Check:Disconnect()
end
--------------------------------------
for _, Anim in pairs(Humanoid:GetPlayingAnimationTracks()) do
local Track
--------------------------------------
if Humanoid.RigType == Enum.HumanoidRigType.R15 then
if Anim.Animation.Parent and Anim.Animation.Parent:IsA("StringValue") then
Track = Anim.Animation.Parent.Name
CurrentAnim = Track
else
Track = Anim.Animation.Name
CurrentAnim = Track
end
end
--------------------------------------
if Track ~= nil then
print(Track)
end
end
end)
--|Expression Handling
RunService.Heartbeat:Connect(function()
if CurrentAnim == "Ring" and Settings:GetAttribute("Expression") ~= "Ring/Bolt" then
Expressions:Swap("Surprised", "Happy", "HappyOpen", "Ring/Bolt")
elseif CurrentAnim == "Cannon" and Settings:GetAttribute("Expression") ~= "Cannon" then
Expressions:Swap("Happy", "Blink", "HappyClosed", "Cannon")
elseif CurrentAnim == "Ventilator" and Settings:GetAttribute("Expression") ~= "Ventilator" then
Expressions:Swap("Happy", "Up", "Curious", "Ventilator")
elseif CurrentAnim == "Drift" and Settings:GetAttribute("Expression") ~= "Drift" then
Expressions:Swap("Happy", "Down", "Curious", "Fall/Drift")
elseif CurrentAnim == "Land" and Settings:GetAttribute("Expression") ~= "Land" then
Expressions:Swap("Happy", "Blink", "BoredClosed", "Land")
elseif CurrentAnim == "Tramp" and Settings:GetAttribute("Expression") ~= "Tramp" then
Expressions:Swap("Angry", "Blink", "BoredClosed", "Tramp")
elseif CurrentAnim == "Hurt" and Settings:GetAttribute("Expression") ~= "Hurt" then
Expressions:Swap("Angry", "Blink", "AngryOpen", "Hurt")
elseif CurrentAnim == "idle" or CurrentAnim == "walk" or CurrentAnim == "run" and Settings:GetAttribute("Expression") ~= "Idle" then
Expressions:Swap("Happy", "Happy", "HappyClosed", "Idle")
elseif CurrentAnim == "jump" and Settings:GetAttribute("Expression") ~= "Jump" then
Expressions:Swap("Happy", "Blink", "HappyClosed", "Jump")
elseif CurrentAnim == "fall" and Settings:GetAttribute("Expression") ~= "Fall" then
Expressions:Swap("Happy", "Down", "HappyClosed", "Fall")
end
end)
- The Expressions ModuleScript itself:
--||Services
local Players = game:GetService("Players")
--||Variables
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Settings = Player:WaitForChild("Settings")
local EyebrowsV = {
Character:WaitForChild("LeftEyebrow").GUI,
Character:WaitForChild("RightEyebrow").GUI
}
local EyesV = {
Character:WaitForChild("LeftEye").GUI,
Character:WaitForChild("RightEye").GUI
}
local MouthV = Character:WaitForChild("Mouth").GUI
local MouthSide = ""
--------------------------------------
local Expressions = {}
--||Functions
function Expressions:MouthFaceCamera(Root, Camera)
local ViewDistance = (Root.Position - Camera.CFrame.Position).Unit
local Dot = ViewDistance:Dot(Root.CFrame.RightVector)
if Dot > -1 and Dot < 0 then
MouthSide = "Left"
elseif Dot < 1 and Dot > 0 then
MouthSide = "Right"
end
end
--------------------------------------
function Expressions:Swap(Eyebrows: string, Eyes: string, Mouth: string, Expression: string)
Settings:SetAttribute("Expression", Expression)
--------------------------------------
for _, Eyebrow : SurfaceGui in ipairs(EyebrowsV) do
for _, Image : ImageLabel in ipairs(Eyebrow:GetChildren()) do
if Image.Name ~= Eyebrows then
Image.Visible = false
else
Image.Visible = true
end
end
end
--------------------------------------
for _, Eye : SurfaceGui in ipairs(EyesV) do
for _, Image : ImageLabel in ipairs(Eye:GetChildren()) do
if Image.Name ~= Eyes then
Image.Visible = false
else
Image.Visible = true
end
end
end
--------------------------------------
for _, Image : ImageLabel in ipairs(MouthV:GetChildren()) do
if not string.match(Image.Name, Mouth) or not string.match(Image.Name, MouthSide) then
Image.Visible = false
elseif string.match(Image.Name, Mouth) and string.match(Image.Name, MouthSide) then
Image.Visible = true
end
end
end
--------------------------------------
return Expressions
- The video showcasing the problem, as we can see the “Drift” expression only stays for a few miliseconds before the “Fall” expressions overrides it?