Fireball building up in hand and then firing..

Hi Everyone,

I'm having a real brain ache trying to figure out the best way to do this and whatever way i've tried I can't seem to get it to work properly with Photon.

Basically when I player hits a particular key I create a prefab which is a sphere with a a photonview, light component and a particle system as a child that is turned off, as the player moves through the animation I increase the intensity of the light until it reaches a certain point then add a rigidbody, turn gravity off on the rigidbody, activate the particle system and finally apply a force to the sphere so it shoots away from the player with a nice firey tail behind it.

In single player I can get this to work nicely but getting it to work and appear for other players is causing me a massive head ache, this is the way I think it should work but apparently it doesn't...

I should mention i've only been at unity for about 3 weeks so I may be missing something obvious! I've tried to provide the code that is relevant.

In my main player script I change the properties of the sphere over the space of the animation so i'm thinking that this sphere script should pick these up and broadcast them to everyone else?

The Sphere:
[code2=csharp]void Start ()
{
pv = GetComponent<PhotonView> ();
}

// Update is called once per frame
void Update ()
{
if (pv.isMine) {
// Writing
intensity = transform.gameObject.GetComponent<Light> ().intensity;
if (transform.parent) {
parent_transform = transform.parent.name;

}

local_position = transform.localPosition;

} else {
// Reading
transform.position = Vector3.Lerp (transform.position, this.correctPlayerPos, Time.deltaTime * 5);
transform.rotation = Quaternion.Lerp (transform.rotation, this.correctPlayerRot, Time.deltaTime * 5);

transform.gameObject.GetComponent<Light> ().intensity = intensity;

transform.parent = transform.Find (parent_transform);
transform.localPosition = local_position;
}
}


void OnPhotonSerializeView (PhotonStream stream, PhotonMessageInfo info)
{
if (stream.isWriting) {
// We own this player: send the others our data
stream.SendNext (transform.position);
stream.SendNext (transform.rotation);
stream.SendNext (intensity);
stream.SendNext (parent_transform);
Debug.Log ("Parent: " + parent_transform);
stream.SendNext (local_position);


} else {
// Network player, receive data
this.correctPlayerPos = (Vector3)stream.ReceiveNext ();
this.correctPlayerRot = (Quaternion)stream.ReceiveNext ();
intensity = (float)stream.ReceiveNext ();
parent_transform = (string)stream.ReceiveNext ();

transform.parent = transform.Find (parent_transform);

local_position = (Vector3)stream.ReceiveNext ();


}
}[/code2]

The player control script:
Currently i'm using an RPC to create and position the ball in the palm of the hand by simply doing
pv.RPC ("makefireball",PhotonTargets.All); if they push f as part of the players update function.

[code2=csharp][RPC]
void makefireball(){
Transform handbone = transform.Find ("NecromancerPelvis/NecromancerSpineCrotch/NecromancerSpineBelly/NecromancerSpineTorax/NecromancerSpineLowChest/NecromancerSpineUpChest/NecromancerScapula/NecromancerLForearmCollarbone/NecromancerLForearm1/NecromancerLForearm2/NecromancerLForearmPalm/NecromancerLFinger01").transform;

GameObject fireball = (GameObject)Instantiate (Resources.Load ("Fireball2"), handbone.position, handbone.rotation);

fireball.transform.parent = handbone;

Vector3 pos = fireball.transform.localPosition;
pos.x = 7.50869e-07f;
pos.y = 0.05350989f;
pos.z = 1.209085e-06f;
fireball.transform.localPosition = pos;
// set off the cast animation
anim.SetBool ("cast_fireball", true);
// tell everyone else...
netFireball = true;

}[/code2]

I'm not using network instantiate since I needed to be able to position it properly relative to the players hand, for some reason OnPhotonSerializeView isn't firing(the one attached to the sphere) since I did that?

I may be going about this completely the wrong way since obviously as you have a flying projectile it needs to be pretty accurate across all players since people are going to want to move out the way. I'm not looking for someone to provide complete code I really just need some pointers on the best way to do this since i've been staring at it for 2 days and can't seem to get it.

Althought it seems like rather a long winded way of doing it i've included a couple of screenshots from single player, the reason it has to be done this way is with enough effort it'll look awesome!


Thanks for your help in advance


Marc

Comments

  • Maybe this helps:
    You can think about the script you run as an animation. No matter how it's actually done, you always keep the sphere in the hand and trigger particles and light intensity.
    You could just trigger that on each client and let each client handle it individually. Use an RPC to sent "i am casting fireball".

    As there is lag, the remote clients will have to catch up, to fire the bullet at about the same time. You can fast-forward or skip into the animation to catch up. Each RPC received also has a timing info if you need it. Alternatively simply assume that 2xGetPing() milliseconds passed since the cast was done.

    Due to lag, the positions on all clients won't always be perfect. Better let one player decide if a bullet hit.
    You write you are inexperienced, so let me add: This seems a trivial issue but it's not. Getting things to sync (near) perfectly is very hard, when there is a random delay while all players act at the same time. Don't give up. Try to fake stuff and try to arrange it in a way you can just "live with it".
  • Hi Tobias,

    Thanks for your reply, actually I moved all the game logic for the fireball animation into a script associated with the fireball, it actually works nicely! I'm starting to get my head round it now I have to say finding good examples and documentation for photon is proving challenging but then again I wasn't expecting this to be easy.

    I am really struggling with the following concepts, basically I need to know how I figure out who(which transform/player character) owns any given photonview?

    Below is the problem I had with my original rpc

    I hit f cast a fireball and call an RPC like so

    [code2=csharp]pv.RPC ("makefireball", PhotonTargets.All);[/code2]

    The RPC is as follows:

    [code2=csharp][RPC]void makefireball(){

    if (pv.isMine) {
    myFinger = transform.FindChild ("NecromancerPelvis/NecromancerSpineCrotch/NecromancerSpineBelly/NecromancerSpineTorax/NecromancerSpineLowChest/NecromancerSpineUpChest/NecromancerScapula/NecromancerLForearmCollarbone/NecromancerLForearm1/NecromancerLForearm2/NecromancerLForearmPalm/NecromancerLFinger01").transform;


    GameObject fireball = (GameObject)Instantiate (FireballObj, myFinger.position, myFinger.rotation);

    fireball.transform.parent = myFinger;
    Debug.Log (myFinger);
    Vector3 pos;// = fireball.transform.localPosition;
    pos.x = 7.50869e-07f;
    pos.y = 0.05350989f;
    pos.z = 1.209085e-06f;
    fireball.transform.localPosition = pos;
    } else {

    Transform playerprefab = pv.transform; // get the right char..


    myFinger = playerprefab.FindChild ("NecromancerPelvis/NecromancerSpineCrotch/NecromancerSpineBelly/NecromancerSpineTorax/NecromancerSpineLowChest/NecromancerSpineUpChest/NecromancerScapula/NecromancerLForearmCollarbone/NecromancerLForearm1/NecromancerLForearm2/NecromancerLForearmPalm/NecromancerLFinger01").transform;
    GameObject fireball = (GameObject)Instantiate (FireballObj, myFinger.position, myFinger.rotation);

    fireball.transform.parent = myFinger;
    Debug.Log (myFinger);
    Vector3 pos;// = fireball.transform.localPosition;
    pos.x = 7.50869e-07f;
    pos.y = 0.05350989f;
    pos.z = 1.209085e-06f;
    fireball.transform.localPosition = pos;
    Debug.Log (playerprefab.name);
    }




    }[/code2]

    The ball is generated properly on the originating players side but not on the other network player, i'm building and running one and then hitting play in the unity ide to get the two players.

    After looking into this a bit further it seems to be because onPhotonSerializeview doesn't get started if your using normal Instantiate so I have to use photonview if I want to have a moving object!

    So lets say I Photonnetwork instantiate a fireball on my local player and properly positioned it I could then do fireball.SOMERPC to get the other clients to the positioning what I can't get my head around is when I call that rpc I have the PhotonView of the object it resides in(in this case the fireball). How do I get the transform of the spawned player?

    Do I grab the player.id and then find the lowest numbered photonview for that id(since that would be the spawned player prefab)?

    I think i'm getting there again not looking for code just some pointers on where to look!

    Thanks


    Marc
  • Hi Tobias,

    One more thing I noticed that actually the owner ID of the photonview is set to scene when using photonnetwork.instantiate , from thinking about it more if I can create that object with an owner ID then its actually pretty straight forward to position it properly!

    Thanks


    Marc
  • Infact hold on, seems I may have been wrong about the owner id, I think I got it i'll post back in bit
  • Nope definately stuck, what i'm doing is in the Start() method for the fireball i'm grabbing the owner id by doing myPhotonView.Owner

    So what I was wondering is how do I get the transform for that owner ID?

    One thing i've learned here is if you object is appearing on the network always put all the logic for messing with it inside the object itself.

    Thanks

    Marc
  • Aha, got it, set a name for each player, use an rpc within the fireball that uses GameObject.Find("MyPlayerName").GetWhateverYouWant

    Finally managed to get my head round this i'll do a little explanation post in a while once i've managed to fully get it working properly!
  • If the PhotonView is on the object you want to affect, then you don't need to PhotonView.Owner and then find it again. Use the shortcut: pv.GameObject.Transform.
    No?
  • Yeah its not unfortunately, the fireball itself is a separate object - i'm still fiddling with it but essentially I was going to call an RPC with the name of the player as a parameter.

    The reason I need the person who made it is so that I can parent it to the persons hand, if I use the networking to transmit the position the ball lags behind the players hand so it needs to be attached as a child and then move as part of the animation.

    I think this is the best way to go?

    Again thanks for your help.

    Marc