Beispiel #1
0
    private void UpdateUserBodyTint()
    {
        VoosActor playerActor = GetPlayerActor();

        if (playerActor == null || userBody == null)
        {
            return;
        }
        if (lastTintPushedToUserBody != null && playerActor.GetTint() == lastTintPushedToUserBody.Value)
        {
            // Already up to date.
            return;
        }
        Color newTint = playerActor.GetTint();

        userBody.SetTint(newTint);
        lastTintPushedToUserBody = newTint;
    }
    void OnColorWheelChanged(Color color)
    {
        // Set tint, but preserve alpha.
        color.a = actor.GetTint().a;
        Color prevColor = actor.GetTint();

        undoStack.PushUndoForActor(
            actor,
            $"Set tint for {actor.GetDisplayName()}",
            actor =>
        {
            actor.SetTint(color);
            actor.ApplyPropertiesToClones();
        },
            actor =>
        {
            actor.SetTint(prevColor);
            actor.ApplyPropertiesToClones();
        });
    }
Beispiel #3
0
    public IEnumerator TestBasic()
    {
        yield return(Setup());

        VoosActor actor = voosEngine.CreateActor(new Vector3(1, 2, 3), Quaternion.identity, _ => { });

        Assert.NotNull(actor);
        Assert.AreEqual(1.0, actor.GetTint().r, 1e-4);

        string brainId    = actor.GetBrainName();
        string behaviorId = NewGUID();
        string js         = @"
        export function onTick(api) {
          setTint(0.12, 0.34, 0.56);
        }
    ";

        behaviorSystem.PutBehavior(behaviorId, new Behavior {
            javascript = js
        });
        var use = new BehaviorUse
        {
            id          = NewGUID(),
            behaviorUri = IdToEmbeddedBehaviorUri(behaviorId)
        };
        var brain = new Brain {
            behaviorUses = new BehaviorUse[] { use }
        };

        behaviorSystem.PutBrain(brainId, brain);

        // Let it run at least one voos update
        yield return(new WaitForEndOfFrame());

        yield return(new WaitForEndOfFrame());

        Assert.AreEqual(0.12, actor.GetTint().r, 1e-4);
    }
Beispiel #4
0
    public IEnumerator TestHandleMultipleInOneFrame()
    {
        yield return(Setup());

        VoosActor actor = voosEngine.CreateActor(new Vector3(1, 2, 3), Quaternion.identity, newActor => { });

        actor.SetTint(new Color(0.1f, 0.1f, 0.1f));
        Assert.NotNull(actor);
        Assert.AreEqual(1.0, actor.transform.position.x, 1e-4);

        string brainId    = actor.GetBrainName();
        string behaviorId = behaviorSystem.GenerateUniqueId();
        string js         = @"
    export function onMoveRight() {
      const c = getTint();
      c.r += 0.1;
      setTint(c.r, c.g, c.b);
    }
    ";

        behaviorSystem.PutBehavior(behaviorId, new Behaviors.Behavior {
            javascript = js
        });
        PutTestUse(new TestUse
        {
            behaviorUri = IdToEmbeddedBehaviorUri(behaviorId),
            brainId     = brainId
        });

        // We expect x to increment by 2..
        voosEngine.EnqueueMessage(new VoosEngine.ActorMessage {
            name = "MoveRight", targetActor = actor.GetName()
        });
        voosEngine.EnqueueMessage(new VoosEngine.ActorMessage {
            name = "MoveRight", targetActor = actor.GetName()
        });

        // Let it run at least one voos update
        yield return(new WaitForEndOfFrame());

        yield return(new WaitForEndOfFrame());

        Assert.AreEqual(0.3, actor.GetTint().r, 1e-4);
    }
    public void AddActor(VoosActor va)
    {
#if USE_PUN
        if (va.reliablePhotonView == null)
        {
            throw new System.Exception("GlobalUnreliableData only accepts actors with reliablePhotonView (not local drafts)");
        }
        if (actors.ContainsKey((short)va.reliablePhotonView.viewID))
        {
            Debug.LogWarning("Adding an actor that is already added.  Is this an ownership transfer?");
            return;
        }
        NetworkedActor na = new NetworkedActor();
        na.actor                    = va;
        na.lastPosition             = va.transform.position;
        na.lastRotation             = va.transform.rotation;
        na.lastColor                = va.GetTint();
        na.lastTransformUpdateFrame = Time.frameCount;
        na.messagesSinceLastUpdate  = 0;
        actors.Add((short)va.reliablePhotonView.viewID, na);
#endif
    }
    byte[] Serialize()
    {
        serializationBytes.Clear();

        VoosNetworkTypes.ShortToBytes stb = new VoosNetworkTypes.ShortToBytes();
        VoosNetworkTypes.UintToBytes  utb = new VoosNetworkTypes.UintToBytes();
        int   totalCount       = 0;
        float totalProbability = 0;

        foreach (KeyValuePair <short, NetworkedActor> na in actors)
        {
            VoosActor va = na.Value.actor;
            if (va != null && va.reliablePhotonView.isMine && !va.IsParented())
            {
                Vector3    p = va.transform.position;
                Quaternion q = va.transform.rotation;
                if (na.Value.lastPosition != p || na.Value.lastRotation != q || na.Value.lastColor != va.GetTint())
                {
                    na.Value.lastPosition             = p;
                    na.Value.lastRotation             = q;
                    na.Value.lastColor                = va.GetTint();
                    na.Value.lastTransformUpdateFrame = Time.frameCount;
                    na.Value.messagesSinceLastUpdate  = 0;
                }
                na.Value.updateProbability = Mathf.Clamp(1.0f / (float)(1 + na.Value.messagesSinceLastUpdate), minimumProbabilityOfUpdate, 1);
                totalProbability          += na.Value.updateProbability;
            }
            totalCount++;
        }
        float probabilityOfPositionUpdate = 1;

        if (totalCount > MaxPositionUpdatesPerTick)
        {
            probabilityOfPositionUpdate = (float)MaxPositionUpdatesPerTick / totalProbability;
        }

        /// Message Header
        /// Transform count - will modify after the fact.
        serializationBytes.Add(0);
        serializationBytes.Add(0);

        /// Timestamp for prediction.
        utb.data = VoosNetworkTypes.CompressFloatToUint24(Time.time);
        serializationBytes.Add(utb.byte0);
        serializationBytes.Add(utb.byte1);
        serializationBytes.Add(utb.byte2);
        int index = 0;

        foreach (KeyValuePair <short, NetworkedActor> na in actors)
        {
            VoosActor va = na.Value.actor;
            if (va != null && va.reliablePhotonView.isMine && !va.IsParented())
            {
                if (Random.value > (probabilityOfPositionUpdate * na.Value.updateProbability))
                {
                    continue;
                }
                na.Value.messagesSinceLastUpdate++;
                /// View ID
                stb.data = (short)va.reliablePhotonView.viewID;
                serializationBytes.Add(stb.byte0);
                serializationBytes.Add(stb.byte1);

                /// Network data bitmask
                UnreliableBitmask mask = UnreliableBitmask.None;
                mask |= va.GetTeleport() ? UnreliableBitmask.Teleport : UnreliableBitmask.None;
                mask |= va.GetEnablePhysics() ? UnreliableBitmask.EnablePhysics : UnreliableBitmask.None;
                serializationBytes.Add((byte)mask);

                // Unset the "teleport" flag, as it's transient and should only be used for one network packet.
                va.SetTeleport(false);

                // SUBTLE: If physics is not enabled, then pos/rot is not likely to
                // change. However, any inaccuracies are also more likely to be noticed
                // (such as static walls being slightly tilted). So given this, always
                // send full precision updates for static objects. Sure, this is less
                // efficient for things like moving platforms which do not have physics
                // but often change, but that's likely to be a minority.

                /// Local Position
                utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.x));
                utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.y));
                utb.WriteUint24(serializationBytes, VoosNetworkTypes.CompressFloatToUint24(na.Value.lastPosition.z));

                // Static - send full precision rotation on change. TODO I'm sure
                // there's some way to compress it to 8 bytes without loss.
                var        ftb = new VoosNetworkTypes.FloatToBytes();
                Quaternion q   = na.Value.lastRotation;
                ftb.SerializeTo(serializationBytes, q.x);
                ftb.SerializeTo(serializationBytes, q.y);
                ftb.SerializeTo(serializationBytes, q.z);
                ftb.SerializeTo(serializationBytes, q.w);

                //Color
                serializationBytes.Add(na.Value.lastColor.r);
                serializationBytes.Add(na.Value.lastColor.g);
                serializationBytes.Add(na.Value.lastColor.b);
                serializationBytes.Add(na.Value.lastColor.a);

                /// Linear Velocity
                Rigidbody rb = va.GetComponent <Rigidbody>();
                Vector3   lv = Vector3.zero;
                if (rb != null && !rb.isKinematic)
                {
                    lv = rb.velocity;
                }
                utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.x);
                serializationBytes.Add(utb.byte0);
                serializationBytes.Add(utb.byte1);
                serializationBytes.Add(utb.byte2);
                utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.y);
                serializationBytes.Add(utb.byte0);
                serializationBytes.Add(utb.byte1);
                serializationBytes.Add(utb.byte2);
                utb.data = VoosNetworkTypes.CompressFloatToUint24(lv.z);
                serializationBytes.Add(utb.byte0);
                serializationBytes.Add(utb.byte1);
                serializationBytes.Add(utb.byte2);
                index++;
            }
        }
        stb.data = (short)index;
        serializationBytes[0] = stb.byte0;
        serializationBytes[1] = stb.byte1;

        if (index == 0)
        {
            return(null);
        }
        return(serializationBytes.ToArray());
    }