![]() |
|
|
#1 |
|
Bone Rotating (client side)
Hello, how can i get bone rotation on client?
I attempt to do SetBoneRotation, but it doesn't work on client, for example on non-dedicated server or single game bone is rotating well. Engine: UE2 (Postal2 edition) Last edited by EvilT-ModZ; 3rd Aug 2011 at 03:20 AM. |
|
|
|
|
|
|
#2 |
|
p.s: script is very simple
Code:
class mgunweapon extends weapon;
const ROT_BONE = 'barrel';
simulated function DoRotate() {
local rotator rotme;
rotme.roll=32768;
SetBoneRotation('ROT_BONE', rotme, 0, 1);
}
function ProjectileFire() {
DoRotate();
}
|
|
|
|
|
|
|
#3 |
|
I'm pretty sure the third parameter of SetBoneRotation() should be set to 1 (or omitted, as 1 is the default) for an effect to become visible. And for a barrel, I think you actually want local space, in other words omit the fourth parameter as well or set it to 0.
__________________
Wormbo's UT/UT2004/UT3 mods | YouTube channel | PlanetJailbreak | Unreal Wiki | Liandri Archives Everything you ever wanted to know about replication | UnrealScript security considerations <elmuerte> you shouldn't do all-nighters, it's a waste of time and effort <TNSe> nono <TNSe> its always funny to find code a week later you dont even remember writing <Pfhoenix> what's worse is when you have a Star Wars moment <Pfhoenix> "Luke! I am your code!" "No! Impossible! It can't be!" |
|
|
|
|
|
|
#4 |
|
Thanks for advise but doesn't work on client(
|
|
|
|
|
|
|
#5 |
|
I found that SetBoneRotation not simulated like in ut2003/2004
Code:
native final function SetBoneRotation( name BoneName, optional rotator BoneTurn, optional int Space, optional float Alpha ); |
|
|
|
|
|
|
#6 |
|
I don't know about Postal2, but in UT2004, the equivalent function of ProjectileFire (DoFireEffect/SpawnProjectile) was only executed on the server (in the weaponFire class, not weapon), so your DoRotate function would only be called there, not on the client. To run on the client you should call your DoRotate function from the appropriate point in the PlayFiring function instead (which should be simulated no matter where it is located).
__________________
"What do you mean it doesn't exist clientside?" Got a Pawn problem? Ask me about: Leaning, Prone, Limiting Strafing, Mantling, Dashing, Crouch Jumping, Using Cover, Parkour Moves My Generic Mods for UT2K4: Yet Another Real-life Mod: Class-based play, generic realistic weapons, unoriginal gameplay, w/ cheap COD4 knockoff ![]() TD Vehicles v124: HMMWV, MI4Hound, Black Hawk & AH-6 Helicopters, Motorcycle, IFAV Jeep, Abrams Tank * The only "truth" is what you can get away with * Last edited by meowcat; 7th Aug 2011 at 11:04 AM. |
|
|
|
|
|
|
#7 | |
|
Quote:
Code:
simulated function Tick(float DeltaTime) {
local rotator rotme;
rotme.yaw = 32768;
SetBoneRotation('FAN_BONE', rotme, 0, 1);
Super.Tick(DeltaTime);
}
|
||
|
|
|
|
|
#8 | |
|
Quote:
Did you make sure the code containing your SetBoneRotation call is executed at all?
__________________
Wormbo's UT/UT2004/UT3 mods | YouTube channel | PlanetJailbreak | Unreal Wiki | Liandri Archives Everything you ever wanted to know about replication | UnrealScript security considerations <elmuerte> you shouldn't do all-nighters, it's a waste of time and effort <TNSe> nono <TNSe> its always funny to find code a week later you dont even remember writing <Pfhoenix> what's worse is when you have a Star Wars moment <Pfhoenix> "Luke! I am your code!" "No! Impossible! It can't be!" Last edited by Wormbo; 8th Aug 2011 at 01:27 AM. |
||
|
|
|
|
|
#9 |
|
Yes, it's successfully working on single-player game and non-dedicated server
|
|
|
|
|
|
|
#10 | |
|
Quote:
Also, for performance reasons, sometimes notify functions are explicitly disabled client-side, look for disable('tick'); in superclass definitions to see if tick is being forcibly disabled. If you want to check whether something is being executed client-side, a quick and dirty way is to deliberately crash the game (logging works too but crashing is quicker ) using:Code:
simulated function Tick(float DeltaTime)
{
Super.Tick(DeltaTime);
if (Level.NetMode != NM_DedicatedServer) // Client or listen server
{
// Do some effects stuff
if (Level.NetMode == NM_Client) // only a client
{
assert(false); // crash the game instantly "assertion failed"
}
}
}
|
||
|
|
|
|
|
#11 | |
|
Quote:
|
||
|
|
|
|
|
#12 |
|
Which means your code is never being executed client-side. What is the superclass of the actor this code is inside, and what is the actor's RemoteRole setting?
|
|
|
|
|
|
|
#13 |
|
|
|
|
|
#14 |
|
It's unlikely that tick() is being executed client-side then, and since it's KActor you can't replicate functions to it (the actor is not "owned" by a client). Change the RemoteRole to ROLE_SimulatedProxy and see if this cures your problem.
Be aware that changing the RemoteRole can affect other things though so you may need to do some more advanced testing, for example if the superclass' tick() function doesn't check whether it's client side or not then it may be necessary to only call the super.tick() on the 'server', like this: Code:
simulated function Tick(float DeltaTime)
{
if (Role == ROLE_Authority) Super.Tick(DeltaTime);
if (Level.NetMode != NM_DedicatedServer)
{
// Do funky client-side stuff
}
}
Another point to note is that having your actor ticked client-side all the time might not be what you really want, for example if the bone rotation effect happens only once you could disable the tick function client-side once the rotation is complete, and re-enable it when needed (for example use a replicated variable and check its value in PostNetReceive. Code:
var byte ClientEffect, ServerEffect;
replication
{
unreliable if (Role == ROLE_Authority)
ServerEffect;
}
simulated function Tick(float DeltaTime)
{
Super.Tick(DeltaTime);
if (Level.NetMode != NM_DedicatedServer)
{
// Do funky client-side bone rotation
if (Level.NetMode == NM_Client && SomeVarIndicatesRotationIsFinished)
disable( 'tick' );
}
}
// Call this function server-side to trigger client-side effect
function ServerTriggerEffect()
{
ServerEffect++;
}
simulated function ClientTriggerEffect()
{
enable( 'tick' );
// Do stuff
}
simulated event PostNetReceive()
{
if (Level.NetMode == NM_Client && ClientEffect < ServerEffect)
{
ClientTriggerEffect();
}
ClientEffect = ServerEffect;
}
defaultproperties
{
bNetNotify=true // Enables the PostNetReceive event
}
__________________
![]() Before you criticise someone, walk a mile in their shoes; that way, when you criticise them you are a mile away and have their shoes. Last edited by EQ²; 8th Aug 2011 at 07:50 AM. |
|
|
|
|
|
|
#15 | |
|
Quote:
Because actor with simulatedproxy have collapsed on client ![]() And "bNetNotify" not written on game's class Actor Last edited by EvilT-ModZ; 8th Aug 2011 at 09:36 AM. |
||
|
|
|
|
|
#16 |
|
Please elaborate? Are you saying that changing it to SimulatedProxy causes the physics to fail client-side? If that's the case then you may have to do the rotation with a "helper" actor. Basically this would be another replicated actor which actually manages the effects for the KActor and can safely be set to SimulatedProxy to run the code you need.
|
|
|
|
|
|
|
#17 | |
|
Quote:
http://s55.radikal.ru/i149/1108/dd/d343e374a968.jpg, you can see: rendering mesh of actor stay static and it's collision and some stuff have moved |
||
|
|
|
|
|
#18 |
|
If making it SimulatedProxy breaks it client-side then you'll have to stick with dumb proxy - this is likely either because some code isn't checking whether Role == Authority and is executing client-side with empty values, or because setting it to SimulatedProxy alters the physics behaviour, either way you need to find another solution.
If your actor has other attached actors you might be able to put your code in them, either that or just make your own attached "helper" actor to just provide the animation. Here's a canned example (pseudocode, I'm typing directly into the edit window not into a nice IDE): Your helper actor: Code:
class BoneRotationHelper extends Actor notplaceable;
var float currentBoneRotation, desiredBoneRotation, boneRotationRate;
var name boneName;
simulated event PreBeginPlay()
{
currentBoneRotation = 0;
disable( 'tick' );
}
// Call this function to begin rotating the specified bone at the specifed rate
simulated function RotateBone(name boneToRotate, float desiredPitch, float desiredRate)
{
currentBoneRotation = MyKActor(Owner).GetBoneRotation( boneToRotate ).Pitch;
desiredBoneRotation = desiredPitch;
boneRotationRate = desiredRate;
boneName = boneToRotate;
enable( 'tick' );
}
simulated event Tick(float DeltaTime)
{
local Rotator boneRotation;
local float deltaPitch;
Super.Tick(DeltaTime);
if (currentBoneRotation < desiredBoneRotation)
deltaPitch = boneRotationRate * DeltaTime;
else if (currentBoneRotation > desiredBoneRotation)
deltaPitch = -boneRotationRate * DeltaTime;
else
disable( 'tick' ); // Target reached, disable ticking
currentBoneRotation += deltaPitch
boneRotation.Pitch = currentBoneRotation;
MyKActor(Owner).SetBoneDirection( boneName, boneRotation );
}
defaultproperties
{
RemoteRole=ROLE_None
}
Code:
class MyKActor extends KActor placeable;
var BoneRotationHelper rotationHelper;
var byte serverEffect, clientEffect;
replication
{
reliable if (Role == ROLE_Authority)
serverEffect;
}
simulated event PreBeginPlay()
{
Super.PreBeginPlay();
// Only need the helper on client, listen server and SP
if (Level.NetMode != NM_DedicatedServer)
{
rotationHelper = Spawn( class'BoneRotationHelper' );
}
}
simulated event PostNetBeginPlay()
{
Super.PostNetBeginPlay();
// Initial replication, set effect counter to avoid triggering
// effect when actor becomes relevant
clientEffect = serverEffect;
}
simulated event Destroyed()
{
// Clean up the helper when we are destroyed
if (rotationHelper != None)
{
rotationHelper.Destroy();
rotationHelper = None;
}
}
// Call this function server-side to trigger the effect, client replication
// is handled by the replicated variable
function TriggerEffect()
{
serverEffect++;
ClientTriggerEffect(); // Trigger event on listen server / single player
}
simulated function ClientTriggerEffect()
{
if (Level.NetMode != NM_DedicatedServer && rotationHelper != None)
{
rotationHelper.RotateBone( 'someBone', 16384, 600 );
}
}
simulated event PostNetReceive()
{
if (Role < ROLE_Authority && serverEffect > clientEffect)
{
clientEffect = serverEffect;
ClientTriggerEffect();
}
}
defaultproperties
{
RemoteRole = ROLE_DumbProxy
bNetNotify = true
}
The example also disables ticking the helper actor when it is not doing any work, this isn't strictly necessary but a useful optimisation in case you have lots of these. You should also note that since we're spawning a new actor we have to manage cleaning it up ourselves, this is managed in the KActor's Destroyed() function. This is just a canned example really but hopefully it helps, sorry if the code doesn't compile but I don't have UT2k4 or an IDE here at work so I've just bashed this out from memory. |
|
|
|
|
|
|
#19 |
|
|
|
|
|
#20 |
|
Afraid not, it looks like they took that function out in the Postal2 build of UE2 (it's not uncommon for licensees to remove functions they don't need and I don't think multiplayer was thought about. Basically you can't use the method above by the looks of it.
So, you can't make it simulatedproxy and you can't do efficient replication on the actor so you'll have to attach the helper actor server-side and do your replication in there. The down side is that because you can't use PostNetReceive you'll have to tick the helper actor all the time and check the value of your replication flag every tick. It sucks and but I can't see there's much alternative really. |
|
|
|
|
![]() |
| Tags |
| bone, boning, postal 2, rotating |
| Thread Tools | |
| Display Modes | |
|
|