makzombie Posted October 19, 2015 Posted October 19, 2015 I'm currently making a mod that moves an object around the player based on their camera and was wondering if it was worth looking at the netimmerse scripts that move nodes and whether the object might be more responsive to camera movements rather than using the translateto/moveto functions. It's difficult to get any sort of fast response from papyrus so anything that would work a little faster would be helpful..
Content Consumer Posted October 19, 2015 Posted October 19, 2015 I'm currently making a mod that moves an object around the player based on their camera and was wondering if it was worth looking at the netimmerse scripts that move nodes and whether the object might be more responsive to camera movements rather than using the translateto/moveto functions. It's difficult to get any sort of fast response from papyrus so anything that would work a little faster would be helpful.. I honestly have no idea about any of it, but I wonder if it might help to ask docclox. He's done some work on getting objects to move about. I think he's just used papyrus, not NI, but he might have some pointers...
Guest Posted October 19, 2015 Posted October 19, 2015 MoveTo is absolutely the faster one. NetImmerse funtions are OK to move single points, not the whole object. Of course MoveTo will immediately move something. So, can I ask WHEN you wish to move objects? From time to time? When you cast a spell? Continuously inside a script? Quick reference: * if you do it once, then do it right. Use SplineTranslateTo. * if you do it constantly (for example while the camera is moving) then just use MoveTo. The movements will be too fast to smooth them with the various TranslateTo.
makzombie Posted October 20, 2015 Author Posted October 20, 2015 I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time.
Guest Posted October 20, 2015 Posted October 20, 2015 I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time. getPosition() gives you the position of the item when the function is called. But the update queue may have up to 4 frames to be rendered. Now. 0.01 seconds is way beyond the max refresh rate for Skyrim, that is 60 FPS, so the minimum time should be about 1sec/60 = 1.01666 so try to set it to 0.017 and probably you will increase the quality (but if the actual FPS you have is less this will just make it worst. So try also 0.025 thay is a reasonable FPS rate pretty much every time.)
makzombie Posted October 20, 2015 Author Posted October 20, 2015 I'm using a constantly script that triggers on update where 0.01 seconds, I've used moveto already and it seems the most rough. Also I dislike the fact it fades the object in and out as it moves and using a proxy object that moves then translating too it only increases the lag when moving. I've managed to smooth it a bit with transform to by using the distance from its goal as the speed, but getting the distance struggles with the same input lag as the other functions do. For example I set up a hot key to check the distance. If I move the mouse left then press it almost instantly, the distance with show as 0, so the getposition function doesn't accurately give the correct position at that time. getPosition() gives you the position of the item when the function is called. But the update queue may have up to 4 frames to be rendered. Now. 0.01 seconds is way beyond the max refresh rate for Skyrim, that is 60 FPS, so the minimum time should be about 1sec/60 = 1.01666 so try to set it to 0.017 and probably you will increase the quality (but if the actual FPS you have is less this will just make it worst. So try also 0.025 thay is a reasonable FPS rate pretty much every time.) Not sure if the change looks smoother, but the input lag is still present, would there be no way around that?
Guest Posted October 20, 2015 Posted October 20, 2015 Without looking at the code (and probably executing some profiling) I cannot really help more.
makzombie Posted October 20, 2015 Author Posted October 20, 2015 Scriptname _mz_FM_TranslateObjectRef extends ObjectReference import Math import Debug import Game actor PlayerRef int TransMode float TransDistance float TSBase float TSMultiplier float UpdateTime float[] property TranslateObjectZOffset auto float[] XPosition float[] YPosition float[] ZPosition globalVariable property _mz_TranslateSpeed auto ;default value 5 globalVariable property _mz_TranslateSpeedMultiplier auto ; default value 3 globalVariable property _mz_TranslateDistance auto ;default value 200 globalVariable property _mz_TranslateMode auto ;default value 1 globalVariable property _mz_UpdateTime auto ;default value 0.01 formlist property _mz_TransformObjectFL auto formlist property _mz_PlaceObjectFL auto bool bKeepUpdating = True Event OnInit() SetModMenuValues() RegisterforKey(45) XPosition = new float[2] YPosition = new float[2] ZPosition = new float[2] PlayerRef = GetPlayer() RegisterforSingleUpdate(UpdateTime) EndEvent Event OnKeyDown(int KeyCode) if KeyCode == 45 ;Debug script ;notification(Distance as string) endif endevent Event OnMenuClose(String MenuName) SetModMenuValues() endEvent Event OnActivate(ObjectReference akActionRef) int iIndex = _mz_TransformObjectFL.Find(GetBaseObject()) float ZOffset = TranslateObjectZOffset[iIndex] ObjectReference CreatedContainer = Placeatme(_mz_PlaceObjectFL.GetAt(iIndex)) CreatedContainer.SetPosition(X,Y,Z-ZOffset) CreatedContainer.SetAngle(GetAngleX(),GetAngleY(),GetAngleZ()) bKeepUpdating = false UnregisterForUpdate() self.disable() self.deleteWhenAble() EndEvent Event OnUpdate() if bKeepUpdating == True float PlayerAngleX = PlayerRef.GetAngleX() float PlayerAngleZ = PlayerRef.GetAngleZ() float PlayerHeight = PlayerRef.GetHeight() ;Translate Mode 0: Orbit player around the X and Y Axis, and only move verticly when looking up/down. XPosition[0] = TransDistance * Sin(PlayerAngleZ) YPosition[0] = TransDistance * Cos(PlayerAngleZ) ZPosition[0] = PlayerHeight +- (GetHeight()/2) + -TransDistance * Tan(PlayerAngleX) ;Translate Mode 1: Orbit the Player in all axis used by camera. XPosition[1] = (TransDistance * Cos(PlayerAngleX)) * Sin(PlayerAngleZ) YPosition[1] = (TransDistance * Cos(PlayerAngleX)) * Cos(PlayerAngleZ) ZPosition[1] = PlayerHeight +- (GetHeight()/2) + -TransDistance * Sin(PlayerAngleX) ;Get distance between objects current position and its goal. float Distance = GetDistanceBetweenPoints(X,Y,Z, PlayerRef.X + XPosition[TransMode], PlayerRef.Y + YPosition[TransMode], PlayerRef.Z + ZPosition[TransMode]) TranslateTo(PlayerRef.X + XPosition[TransMode], PlayerRef.Y + YPosition[TransMode], PlayerRef.Z + ZPosition[TransMode], 0, 0, PlayerAngleZ,TSBase + Distance * TSMultiplier, 0) registerForSingleUpdate(UpdateTime) else UnregisterForUpdate() endif EndEvent float Function GetDistanceBetweenPoints(float x1,float y1, float z1, float x2, float y2, float z2) return (sqrt(pow((x1-x2), 2) + pow((y1-y2), 2) + pow((z1-z2), 2))) EndFunction Function SetModMenuValues() notification("Update Variables") UpdateTime = _mz_UpdateTime.GetValueInt() TransMode = _mz_TranslateMode.GetValueInt() TransDistance = _mz_TranslateDistance.GetValue() TSBase = _mz_TranslateSpeed.GetValue() TSMultiplier = _mz_TranslateSpeedMultiplier.GetValue() EndFunction
Guest Posted October 20, 2015 Posted October 20, 2015 The code is already pretty good. Use this one to skip some trigonometric calculations (that are heavy), and because you are using only one "TransMode" at time, you can avoid to always calculate the two and then use only one.And you can try to simplify the distance formula by removing the pow and use a normal multiplication (more efficient).Or better, avoid to use a function to calculate it, and put the code inline. In scripting languages calling a function has a huge performance impact when there are many parameters. float PlayerAngleX = PlayerRef.GetAngleX() float PlayerAngleZ = PlayerRef.GetAngleZ() float PlayerHeight = PlayerRef.GetHeight() float plSinZ = Sin(PlayerAngleZ) float plCosZ = Cos(PlayerAngleZ) float theXPos = 0.0 float theYPos = 0.0 float theZPos = 0.0 if TransMode ;Translate Mode 1: Orbit the Player in all axis used by camera. float trDisPlCosX = TransDistance * Cos(PlayerAngleX) theXPos = trDisPlCosX * plSinZ theYPos = trDisPlCosX * plCosZ theZPos = PlayerHeight - (GetHeight()/2 + TransDistance * Sin(PlayerAngleX)) else ;Translate Mode 0: Orbit player around the X and Y Axis, and only move vertically when looking up/down. theXPos = TransDistance * plSinZ theYPos = TransDistance * plCosZ theZPos = PlayerHeight - (GetHeight()/2 + TransDistance * Tan(PlayerAngleX)) endIf float plX = PlayerRef.X + theXPos float plY = PlayerRef.Y + theYPos float plZ = PlayerRef.Z + theZPos float Distance = sqrt((X-plX)*(X-plX) + (Y-plY)*(Y-plY) + (Z-plZ)*(Z-plZ)) TranslateTo(plX, plY, plZ, 0, 0, PlayerAngleZ, TSBase + Distance * TSMultiplier, 0) EDIT: I added the missing varaible, and I did another small optimization to avoid to have a negation and an addition of the same item. Usually a subtraction is more efficient because is a single operand.
makzombie Posted October 20, 2015 Author Posted October 20, 2015 Thank you =), I will give it a try when I get home tonight Edit - wondering what trDisPlCosX is?
Guest Posted October 20, 2015 Posted October 20, 2015 Thank you =), I will give it a try when I get home tonight Edit - wondering what trDisPlCosX is? Oops. I forgot to add it: float trDisPlCosX = TransDistance * Cos(PlayerAngleX) Use it only for TransMode==0, it is not used in the other case, so no need to calculate it.
TDA Posted October 20, 2015 Posted October 20, 2015 Once I needed to move five actors on a spiral upwards. And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors . To make the scene I had to overclock the processor. What's the problem with Papyrus? How to control the object in the Game World each frame?
Guest Posted October 20, 2015 Posted October 20, 2015 Once I needed to move five actors on a spiral upwards. And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors . What's the problem with Papyrus? The problem was some lagging. The author of this post uses a cyclic script to constantly position one object relative to the player position. I only optimized a little his code for performance. For sure a SKSE plugin in C++ will be faster. But not too much, because the "heavy" functions are moveTo and translateTo. And those are internal.
TDA Posted October 20, 2015 Posted October 20, 2015 Once I needed to move five actors on a spiral upwards. And so far I do not understand how to control the position of the actor by the parametric function, ie each frame. When the faster control then there is more C ++ errors . What's the problem with Papyrus? The problem was some lagging. The author of this post uses a cyclic script to constantly position one object relative to the player position. I only optimized a little his code for performance. For sure a SKSE plugin in C++ will be faster. But not too much, because the "heavy" functions are moveTo and translateTo. And those are internal. i mean too, a parametric function suggests cycles https://en.wikipedia.org/wiki/Parametric_equation But Why??? Skyrim soo slowww...
makzombie Posted October 21, 2015 Author Posted October 21, 2015 Movements looking pretty smooth now =) still nothing to be done about the input lag i'm assuming.
Guest Posted October 21, 2015 Posted October 21, 2015 Movements looking pretty smooth now =) still nothing to be done about the input lag i'm assuming. Please give me some clues about what the "Input Lag" is.
makzombie Posted October 22, 2015 Author Posted October 22, 2015 Just the time between moving the mouse left or right and the object starting to move.
Guest Posted October 23, 2015 Posted October 23, 2015 Just the time between moving the mouse left or right and the object starting to move. OK. You run your code to move the object using the OnUpdate. OnUpdate has a low execution priority. First the game calculates the positions and the whole 3D scene, then checks for the internal events, then renders the scene (in a parallel task), then runs the scripts. Every rendered frame. Not parallel. Sequential. Now, if there is not enough time, your script will be called not every frame but a little bit less. So you will start noticing some lags. Again, you cannot rely on a static number to predict when the next frame will be rendered. It is pretty much impossible to do it. SKSE gives you some hint about the frame rate. You may wish to use them to calculate the amount of fraction of second you have to wait. But still it will not be perfect. To have a perfect result you need to handle this directly on the scene calculation pipeline. And this is not accessible through scripting.
makzombie Posted October 23, 2015 Author Posted October 23, 2015 I thought as much.. I'm happy with how its working anyway, just making sure there wasn't anything else to be done. Thank you very much for your help and your insight =)
Recommended Posts
Archived
This topic is now archived and is closed to further replies.