Blinking: Difference between revisions

From FiguraMC
No edit summary
m modelpart indexing reference
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== How to blink ==
[[File:EyeGroup.png|thumb]] Avatars may blink as a means to convey a character's personality and suggest liveliness. To blink, you must first have eyes that have been split into a separate [[ModelPart]]. Your script will scale this group to simulate blinking.
First, you need to have eyes to scale. I'm gonna store them in a variable for easier accessing, as well as how fast I want to blink (in ticks). Your path will be different
To begin with, define variables containing parameters the script will use: the [[ModelPart Indexing|path to]] the eye model, their height, and the length of the blinking animation.
[[File:EyeGroup.png|thumb]]
<syntaxHighlight lang="lua">
<syntaxHighlight lang="lua">
local eyes = models.model.root.UpperBody.TheHead.Eyes
local eyes = models.model.root.UpperBody.TheHead.Eyes
local EYE_HEIGHT = 2 --The height of your eyes in blockbench units
local BLINK_RATE = 4 * 20 -- 4 Seconds
local BLINK_RATE = 4 * 20 -- 4 Seconds
</syntaxHighlight>
</syntaxHighlight>The <code>BLINK_RATE</code> particle is multiplied by 20 as the script will deal in ticks, and there are 20 ticks in a second.


Next, I want to create a <code>TICK</code> event to set when my eyes blink, as well as 5 variables: tick, oldScale, newScale, oldPos, and newPos, initialized as shown
Next, the logic that determines when to blink will be performed in a <code>TICK</code> event. 4 new variables will also be needed to store the calculated position and scale for the eyes, alongside a simple timer. These will be initialised outside of the <code>TICK</code> event.
<syntaxHighlight lang="lua">
<syntaxHighlight lang="lua">
local oldScale = vec(1, 1, 1)
local oldScale = vec(1, 1, 1)
Line 16: Line 16:
local tick = 0
local tick = 0
function events.TICK()
function events.TICK()
  -- Sets old pos and scale for later interpolation
   oldPos = newPos
   oldPos = newPos
   oldScale = newScale
   oldScale = newScale
   tick = tick + 1
   tick = tick + 1


  -- If time to blink, set new position and scale to close the eyes, otherwise open them
   if tick % BLINK_RATE == 0 then
   if tick % BLINK_RATE == 0 then
     newScale = vec(1, 0, 1)
     newScale = vec(1, 0, 1)
     newPos = vec(0, -1 --[[Half the height of your eyes]], 0)
     newPos = vec(0, EYE_HEIGHT / -2, 0)
   else
   else
     newScale = vec(1, 1, 1)
     newScale = vec(1, 1, 1)
Line 30: Line 32:
</syntaxHighlight>
</syntaxHighlight>


Finally, you want to create a <code>RENDER</code> event to make the blinking smooth
In order to give the blinking a smooth appearance, the rendered position and scale will be calculated and set in a <code>RENDER</code> event, using the variables initialized earlier.


<syntaxHighlight lang="lua">
<syntaxHighlight lang="lua">
function events.RENDER(delta)
function events.RENDER(delta)
  -- This interpolates the blinking to make for a smooth blink
   local scale = math.lerp(oldScale, newScale, delta)
   local scale = math.lerp(oldScale, newScale, delta)
   local pos = math.lerp(oldPos, newPos, delta)
   local pos = math.lerp(oldPos, newPos, delta)
Line 40: Line 43:
end
end
</syntaxHighlight>
</syntaxHighlight>
[[Category:Tutorials]]

Latest revision as of 16:54, 27 September 2024

Avatars may blink as a means to convey a character's personality and suggest liveliness. To blink, you must first have eyes that have been split into a separate ModelPart. Your script will scale this group to simulate blinking.

To begin with, define variables containing parameters the script will use: the path to the eye model, their height, and the length of the blinking animation.

local eyes = models.model.root.UpperBody.TheHead.Eyes
local EYE_HEIGHT = 2 --The height of your eyes in blockbench units
local BLINK_RATE = 4 * 20 -- 4 Seconds

The BLINK_RATE particle is multiplied by 20 as the script will deal in ticks, and there are 20 ticks in a second.

Next, the logic that determines when to blink will be performed in a TICK event. 4 new variables will also be needed to store the calculated position and scale for the eyes, alongside a simple timer. These will be initialised outside of the TICK event.

local oldScale = vec(1, 1, 1)
local newScale = vec(1, 1, 1)
local oldPos = vec(0, 0, 0)
local newPos = vec(0, 0, 0)

local tick = 0
function events.TICK()
  -- Sets old pos and scale for later interpolation
  oldPos = newPos
  oldScale = newScale
  tick = tick + 1

  -- If time to blink, set new position and scale to close the eyes, otherwise open them
  if tick % BLINK_RATE == 0 then
    newScale = vec(1, 0, 1)
    newPos = vec(0, EYE_HEIGHT / -2, 0)
  else
    newScale = vec(1, 1, 1)
    newPos = vec(0, 0, 0)
  end
end

In order to give the blinking a smooth appearance, the rendered position and scale will be calculated and set in a RENDER event, using the variables initialized earlier.

function events.RENDER(delta)
  -- This interpolates the blinking to make for a smooth blink
  local scale = math.lerp(oldScale, newScale, delta)
  local pos = math.lerp(oldPos, newPos, delta)

  eyes:setPos(pos):setScale(scale)
end