Talk:SetScale - ObjectReference
Warning! - Calling this repeatedly (for example to make a transition animation from large to small by doing it in steps) can currently cause a crash-to-desktop or C++ error popup and lock up! (Also, This function does NOT affect the object's collision information. It may LOOK bigger or smaller, but it's not REALLY bigger or smaller as far as the game is concerned.) RedwoodElf
Thanks RedwoodElf. I added this to the main page. Chesko (talk) 21:59, 23 July 2012 (EDT)Chesko
- This issue was reported 12 yrs ago during a time where the current version of Skyrim was 32 bits. I have tested this function to work consistently in loops and no crashes or C++ errors on the much more modern 64bit version of Skyrim. Therefore I'm lead to believe that successive calls to this function is now safe. I will leave the warning about the crash on the main page though as there might be still folks out there modding for the 32 bit version. --TwilightSky (talk) 06:30, 28 May 2024 (EDT)
The way it actually works[edit source]
SetScale() is not cumulative. You cannot SetScale() an object and then SetScale() it again based on the new scale. SetScale always operates on the original object scale.
Additionally, it should be understood that SetScale() is not an operation that sets scale directly. Rather, it is a multiplication equation.
If an object's original scale is 1.3, SetScale(1.0) will set the object's scale to 1.3 (unchanged). This is because of what SetScale actually does under the hood, which is:
SetScale(float) = original object scale * float
This means that SetScale(1.0) will always scale an object to be the size it originally was. It also means that in order to accurately change the size of an object to be different from its original size, you must include a target scale in the equation and figure out the percentage difference (unless the object's true original scale is 1.0, which is rare for actors, due to race and sex being considered, plus custom NPC scaling).
First, get the size:
fNaturalScale = actorVar.GetScale()
Then, create a scaling factor based on your ideal target scale. For this example, we'll say we want the actor to be 1.0:
fScalingFactor = (1.0 / fNaturalScale)
Now you can use SetScale on the actor:
actorVar.SetScale(fScalingFactor)
The actor will now be within 99.99% of 1.0 (it can't get better due to Skyrim's limited floating point precision, which is also seen in Skyrim's own RaceToScale furniture).
Do not reverse the equation in order to set the actor back to its original size. Remember, SetScale always multiplies by the object's original scale. So, just tell the object to be 100% of its original size, like this:
actorVar.SetScale(1.0)
The reversion operation will be 100% accurate, because there was no division in the math. We simply told the object to be its original size.
NOTE: When testing GetScale(), Debug.MessageBox() is slower than ensuing processes possibly due to a lower parallel processing priority or simply because screen display commands take more time. This means you must put delays after each GetScale() before using MessageBox() in order to display the results correctly. You can do this with Utility.Wait(). 1-5 seconds is enough delay, depending on the overall processing being performed. These delays do not need to exist in your final code (unless the goal of your code is to display scaling results in a message box).
NOTE2: It is possible that the crash previously described by RedwoodElf is a result of not understanding that SetScale is not cumulative and attempts were being made to reach a target scale by using SetScale on a previous SetScale result. This would result in the target scale never being reached and an infinite loop could ensue trying to reach it, due to Skyrim's limited floating point processing. SetScale would end up eternally multiplying original object scale by the same number before the goal scale was ever reached. Long story short, don't use SetScale in a loop.