Error you have missing monobehaviours on your gameobjects

Hello, So after literally days of troubleshooting this issue, I'm giving up and want to try getting some help here.

Hello,
So after literally days of troubleshooting this issue, I’m giving up and want to try getting some help here.

Unfortunately, I searched this error here and didn’t really get an answer for my issue.

I’ll try to put as much context as I can to avoid that you miss important information to help me:

Scenes setup:
«A»: Main Menu scene
«B»: Lobby Scene

There is then a play scene but this doesn’t matter anymore as the error only comes in the lobby scene because of the first Player models instantiation.

In Scene «A», Player 1 through the UI can create a room. there are no Photon involved here, clicking on the Create room button setup a bunch of variables and Load Scene «B»

In Scene «B», Player 1 through a lobby script, creates the Room. Then in the network manager it uses the photon Callback

public override void OnJoinedRoom()

In there it checks if we are Master Client, if yes we setup some room props and trigger then the instantiation of the Player Prefab using of course:

PhotonNetwork.Instantiate()

From the point in time, everything works perfectly fine

At this point, Player 2 decides to join the game. Same, Scene «A», only UI without any photon magic in this scene, it just save the room name variable and Load Scene «B» (I tried with PhotonNetwork.LoadLevel(«sceneName») too)

In that scene Player 2 Join the room and that’s where the disaster starts!

As soon as we join the room I get the error message. I know the error is longer that usual but I added some stuff in the Debug.Log to try to pin point what RPC was the cause from where to who etc.

ERROR You have missing MonoBehaviours on your gameobjects!|| And that is this RPC: UpdateCharacter|| Sender is: #01 'Necka' || Receiver might be: [1001] Photon_Player_Base_V1 - Remote [MasterClient]
UnityEngine.Debug:LogError (object)
Photon.Pun.PhotonNetwork:ExecuteRpc (ExitGames.Client.Photon.Hashtable,Photon.Realtime.Player) (at Assets/____Assets/__Asset Store/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs:473)
Photon.Pun.PhotonNetwork:OnEvent (ExitGames.Client.Photon.EventData) (at Assets/____Assets/__Asset Store/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs:2210)
Photon.Realtime.LoadBalancingClient:OnEvent (ExitGames.Client.Photon.EventData) (at Assets/____Assets/__Asset Store/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:3336)
ExitGames.Client.Photon.PeerBase:DeserializeMessageAndCallback (ExitGames.Client.Photon.StreamBuffer) (at D:/Dev/Work/photon-dotnet-sdk/PhotonDotNet/PeerBase.cs:891)
ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands () (at D:/Dev/Work/photon-dotnet-sdk/PhotonDotNet/EnetPeer.cs:558)
ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands () (at D:/Dev/Work/photon-dotnet-sdk/PhotonDotNet/PhotonPeer.cs:1837)
Photon.Pun.PhotonHandler:Dispatch () (at Assets/____Assets/__Asset Store/Photon/PhotonUnityNetworking/Code/PhotonHandler.cs:223)
Photon.Pun.PhotonHandler:FixedUpdate () (at Assets/____Assets/__Asset Store/Photon/PhotonUnityNetworking/Code/PhotonHandler.cs:149)

As previously stated, here Player 2 through the OnJoinedRoom() Photon callback check if were are master and as it’s not, it just go straight to instantiating his own Player Prefab.

The error happens before the instantiation of the Prefab. And that’s where I understand why. The RPC is supposed to be received from a component that’s on the Player Prefab. I didn’t instantiate it yet, so it can’t receive it.

The fun part of course is that this error is triggered only once and that absolutely everything is working fine after the instantiation, there are no problems at all. Everything is synced etc. So you could say «ok just ignore the error and move on» But I have OCD with those red lines. It doesn’t look professional in the Player Log either and I’m not accepting errors in my project, simple as that :)

More info:

The RPC is sent like this from this Character script located on the Player Prefab:

public override void OnPlayerEnteredRoom(Player player)
        {
            if (photonView.IsMine && gameObject.activeSelf)
            {
var lcm = Locomotion;
                photonView.RPC(RPC_CHARACTER, player, transform.position, lcm.canUseNavigationMesh, currentControls, new Vector2(Locomotion.runSpeed, currentAngularSpeed), 
                    currentGravity, currentJump, (int)lcm.faceDirection, syncAttachments ? SerializeAttachments() : emptyHashtable);
            }
        }

The RPC is received as:

[PunRPC]
        private void UpdateCharacter(Vector3 position, bool canUseNavigationMesh, 
            Vector2 controls, Vector2 speed, Vector2 gravity, Vector2 jump, int faceDirection, Hashtable attachments)
        {
                       Some code
        }

At that point I have no clue on how to troubleshoot this issue anymore. Do be fully transparent, I’m using a Unity module which lift the heavy weight on the Photon side and allow me to do most things in a visual scripting way. But I do know my way around code but that’s also the reason why I’m not sharing too much details on code here, but can answer any questions of course!

Thank you in advance for your support, I hope my post isn’t too complicated to understand

Содержание

  1. ERROR You have missing MonoBehaviours on your gameobjects!
  2. Damage dealing scripts
  3. Comments
  4. Error you have missing monobehaviours on your gameobjects
  5. Error you have missing monobehaviours on your gameobjects
  6. MonoBehaviour
  7. Success!
  8. Submission failed
  9. Description
  10. Properties
  11. Public Methods
  12. Static Methods
  13. Messages
  14. Inherited Members
  15. Properties
  16. Public Methods
  17. Static Methods
  18. Operators

ERROR You have missing MonoBehaviours on your gameobjects!

Hello,
So after literally days of troubleshooting this issue, I’m giving up and want to try getting some help here.

Unfortunately, I searched this error here and didn’t really get an answer for my issue.

I’ll try to put as much context as I can to avoid that you miss important information to help me:

Scenes setup:
«A»: Main Menu scene
«B»: Lobby Scene

There is then a play scene but this doesn’t matter anymore as the error only comes in the lobby scene because of the first Player models instantiation.

In Scene «A», Player 1 through the UI can create a room. there are no Photon involved here, clicking on the Create room button setup a bunch of variables and Load Scene «B»

In Scene «B», Player 1 through a lobby script, creates the Room. Then in the network manager it uses the photon Callback

In there it checks if we are Master Client, if yes we setup some room props and trigger then the instantiation of the Player Prefab using of course:

From the point in time, everything works perfectly fine

At this point, Player 2 decides to join the game. Same, Scene «A», only UI without any photon magic in this scene, it just save the room name variable and Load Scene «B» (I tried with PhotonNetwork.LoadLevel(«sceneName») too)

In that scene Player 2 Join the room and that’s where the disaster starts!

As soon as we join the room I get the error message. I know the error is longer that usual but I added some stuff in the Debug.Log to try to pin point what RPC was the cause from where to who etc.

As previously stated, here Player 2 through the OnJoinedRoom() Photon callback check if were are master and as it’s not, it just go straight to instantiating his own Player Prefab.

The error happens before the instantiation of the Prefab. And that’s where I understand why. The RPC is supposed to be received from a component that’s on the Player Prefab. I didn’t instantiate it yet, so it can’t receive it.

The fun part of course is that this error is triggered only once and that absolutely everything is working fine after the instantiation, there are no problems at all. Everything is synced etc. So you could say «ok just ignore the error and move on» But I have OCD with those red lines. It doesn’t look professional in the Player Log either and I’m not accepting errors in my project, simple as that

The RPC is sent like this from this Character script located on the Player Prefab:

The RPC is received as:

At that point I have no clue on how to troubleshoot this issue anymore. Do be fully transparent, I’m using a Unity module which lift the heavy weight on the Photon side and allow me to do most things in a visual scripting way. But I do know my way around code but that’s also the reason why I’m not sharing too much details on code here, but can answer any questions of course!

Thank you in advance for your support, I hope my post isn’t too complicated to understand

Источник

Damage dealing scripts

Okay i posted this question a whiles back and didn’t really get the help i needed, i’m trying to set up third person combat but i can’t seem to deal damage to the other player i even purchased the M2H guides and tried using the fps example i’ll show how far I’ve got then i’ll explain more
[code2=csharp]public int damage = 50;
public int range = 10;

void MeleeCombat()
<
Vector3 direction = transform.TransformDirection(Vector3.forward);
RaycastHit hit;

// Did we hit anything?
if (Physics.Raycast(transform.position, direction * 2, out hit))
<
hit.collider.SendMessage(«ApplyDamage», damage, SendMessageOptions.DontRequireReceiver);
>

// Update is called once per frame
void Update () <
Vector3 direction = transform.TransformDirection(Vector3.forward);
Debug.DrawRay(transform.position,direction * 2,Color.blue);
if (Input.GetButtonDown(«Fire1»))
<
MeleeCombat();
>
>

void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
<
if(stream.isWriting)
<

>
>[/code2]
This is my damage dealing script and is attached to an empty gameobject on the player prefab
[code2=csharp]public int hp = 100;

void ApplyDamage(int Damage)
<

hp -= (int)Damage;
if (hp 0

Maybe the HP setting doesn’t work, because you have those errors.
Let’s fix them first.

«You have missing MonoBehaviours on your gameobjects!»
I had to look this up but I can’t yet explain it. With photonNetview.GetComponents (), we get all MonoBehaviours on the gameObject that we target. For some reason, this is null, causing the output.
Usually, this doesn’t happen. Maybe you remove a component from your GameObjects or do something similar with it.
Find out which GameObject this is and check if you have scripts on that. You can’t call RPCs on GameObjects which don’t have scripts (which implement the RPC).

PhotonView with ID 1001 has 2 methods «setHP» that takes 1 argument(s): Int32. Should be just one?
This error sounds like you didn’t copy all of the relevant code into your post. You seem to have 2 implementations of setHP(someParameter).
Try to find the duplicate and get rid of it. You can use multiple names for RPCs to do different things.

Источник

Error you have missing monobehaviours on your gameobjects

How to reproduce:
1. Open the attached «Repro.zip» project
2. Open the Main scene
3. Enter Play mode
4. Observe the Console errors
5. In Hierarchy, select «GameObject» prefab and remove the reference to non-MonoBehaviourscript
6. Enter the Play mode again
7. Observe the same Console errors.

Expected behavior: Along with (or instead of) the below-mentioned errors, the user is informed about the class that is not derived from MonoBehaviour or ScriptableObject.
Actual behavior: The error message that informs about the class that is not derived from MonoBehaviour or ScriptableObject is shown only when entering Play mode in the scene that contains a GameObject with such non-MonoBehaviour component.

Reproducible with — 2017.3.0a1, 2017.4.19f1, 2018.3.3f1, 2019.1.0b1, 2019.2.0a3

Errors thrown:
— «‘ ‘ is missing the class attribute ‘ExtensionOfNativeClass’!» (does not appear in 2017.4)
— «GameObject (named ‘ ‘) references runtime script in scene file. Fixing!»

Workaround: Manually remove non-MonoBehavour script components from GameObjects and Prefabs.

Resolution Note (2018.3.X):

Until the reference to the script is removed from the prefab this error will continue to pop up. This is because entering play mode works by loading the scene and the prefab (which causes the error), then merge the prefab into scene during which the component is removed. So removing it in the scene is not enough the reference also needs to be removed from the prefab.

Источник

Error you have missing monobehaviours on your gameobjects

How to reproduce:
1. Open the attached «Repro.zip» project
2. Open the Main scene
3. Enter Play mode
4. Observe the Console errors
5. In Hierarchy, select «GameObject» prefab and remove the reference to non-MonoBehaviourscript
6. Enter the Play mode again
7. Observe the same Console errors.

Expected behavior: Along with (or instead of) the below-mentioned errors, the user is informed about the class that is not derived from MonoBehaviour or ScriptableObject.
Actual behavior: The error message that informs about the class that is not derived from MonoBehaviour or ScriptableObject is shown only when entering Play mode in the scene that contains a GameObject with such non-MonoBehaviour component.

Reproducible with — 2017.3.0a1, 2017.4.19f1, 2018.3.3f1, 2019.1.0b1, 2019.2.0a3

Errors thrown:
— «‘ ‘ is missing the class attribute ‘ExtensionOfNativeClass’!» (does not appear in 2017.4)
— «GameObject (named ‘ ‘) references runtime script in scene file. Fixing!»

Workaround: Manually remove non-MonoBehavour script components from GameObjects and Prefabs.

Resolution Note (2018.3.X):

Until the reference to the script is removed from the prefab this error will continue to pop up. This is because entering play mode works by loading the scene and the prefab (which causes the error), then merge the prefab into scene during which the component is removed. So removing it in the scene is not enough the reference also needs to be removed from the prefab.

Источник

MonoBehaviour

class in UnityEngine

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Submission failed

For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Description

MonoBehaviour is the base class from which every Unity script derives.

When you use C#, you must explicitly derive from MonoBehaviour.

This class doesn’t support the null-conditional operator (?.) and the null-coalescing operator (??).

For code samples, see the individual MonoBehaviour methods.

Note: There is a checkbox for enabling or disabling MonoBehaviour in the Unity Editor. It disables functions when unticked. If none of these functions are present in the script, the Unity Editor does not display the checkbox. The functions are:

See Also: The Deactivating GameObjects page in the manual.

Properties

runInEditMode Allow a specific instance of a MonoBehaviour to run in edit mode (only available in the editor).
useGUILayout Disabling this lets you skip the GUI layout phase.

Public Methods

CancelInvoke Cancels all Invoke calls on this MonoBehaviour.
Invoke Invokes the method methodName in time seconds.
InvokeRepeating Invokes the method methodName in time seconds, then repeatedly every repeatRate seconds.
IsInvoking Is any invoke on methodName pending?
StartCoroutine Starts a Coroutine.
StopAllCoroutines Stops all coroutines running on this behaviour.
StopCoroutine Stops the first coroutine named methodName, or the coroutine stored in routine running on this behaviour.

Static Methods

print Logs message to the Unity Console (identical to Debug.Log).

Messages

Awake Awake is called when the script instance is being loaded.
FixedUpdate Frame-rate independent MonoBehaviour.FixedUpdate message for physics calculations.
LateUpdate LateUpdate is called every frame, if the Behaviour is enabled.
OnAnimatorIK Callback for setting up animation IK (inverse kinematics).
OnAnimatorMove Callback for processing animation movements for modifying root motion.
OnApplicationFocus Sent to all GameObjects when the player gets or loses focus.
OnApplicationPause Sent to all GameObjects when the application pauses.
OnApplicationQuit Sent to all GameObjects before the application quits.
OnAudioFilterRead If OnAudioFilterRead is implemented, Unity will insert a custom filter into the audio DSP chain.
OnBecameInvisible OnBecameInvisible is called when the renderer is no longer visible by any camera.
OnBecameVisible OnBecameVisible is called when the renderer became visible by any camera.
OnCollisionEnter OnCollisionEnter is called when this collider/rigidbody has begun touching another rigidbody/collider.
OnCollisionEnter2D Sent when an incoming collider makes contact with this object’s collider (2D physics only).
OnCollisionExit OnCollisionExit is called when this collider/rigidbody has stopped touching another rigidbody/collider.
OnCollisionExit2D Sent when a collider on another object stops touching this object’s collider (2D physics only).
OnCollisionStay OnCollisionStay is called once per frame for every Collider or Rigidbody that touches another Collider or Rigidbody.
OnCollisionStay2D Sent each frame where a collider on another object is touching this object’s collider (2D physics only).
OnConnectedToServer Called on the client when you have successfully connected to a server.
OnControllerColliderHit OnControllerColliderHit is called when the controller hits a collider while performing a Move.
OnDestroy Destroying the attached Behaviour will result in the game or Scene receiving OnDestroy.
OnDisable This function is called when the behaviour becomes disabled.
OnDisconnectedFromServer Called on the client when the connection was lost or you disconnected from the server.
OnDrawGizmos Implement OnDrawGizmos if you want to draw gizmos that are also pickable and always drawn.
OnDrawGizmosSelected Implement OnDrawGizmosSelected to draw a gizmo if the object is selected.
OnEnable This function is called when the object becomes enabled and active.
OnFailedToConnect Called on the client when a connection attempt fails for some reason.
OnFailedToConnectToMasterServer Called on clients or servers when there is a problem connecting to the MasterServer.
OnGUI OnGUI is called for rendering and handling GUI events.
OnJointBreak Called when a joint attached to the same game object broke.
OnJointBreak2D Called when a Joint2D attached to the same game object breaks.
OnMasterServerEvent Called on clients or servers when reporting events from the MasterServer.
OnMouseDown OnMouseDown is called when the user has pressed the mouse button while over the Collider.
OnMouseDrag OnMouseDrag is called when the user has clicked on a Collider and is still holding down the mouse.
OnMouseEnter Called when the mouse enters the Collider.
OnMouseExit Called when the mouse is not any longer over the Collider.
OnMouseOver Called every frame while the mouse is over the Collider.
OnMouseUp OnMouseUp is called when the user has released the mouse button.
OnMouseUpAsButton OnMouseUpAsButton is only called when the mouse is released over the same Collider as it was pressed.
OnNetworkInstantiate Called on objects which have been network instantiated with Network.Instantiate.
OnParticleCollision OnParticleCollision is called when a particle hits a Collider.
OnParticleSystemStopped OnParticleSystemStopped is called when all particles in the system have died, and no new particles will be born. New particles cease to be created either after Stop is called, or when the duration property of a non-looping system has been exceeded.
OnParticleTrigger OnParticleTrigger is called when any particles in a Particle System meet the conditions in the trigger module.
OnParticleUpdateJobScheduled OnParticleUpdateJobScheduled is called when a Particle System’s built-in update job has been scheduled.
OnPlayerConnected Called on the server whenever a new player has successfully connected.
OnPlayerDisconnected Called on the server whenever a player disconnected from the server.
OnPostRender Event function that Unity calls after a Camera renders the scene.
OnPreCull Event function that Unity calls before a Camera culls the scene.
OnPreRender Event function that Unity calls before a Camera renders the scene.
OnRenderImage Event function that Unity calls after a Camera has finished rendering, that allows you to modify the Camera’s final image.
OnRenderObject OnRenderObject is called after camera has rendered the Scene.
OnSerializeNetworkView Used to customize synchronization of variables in a script watched by a network view.
OnServerInitialized Called on the server whenever a Network.InitializeServer was invoked and has completed.
OnTransformChildrenChanged This function is called when the list of children of the transform of the GameObject has changed.
OnTransformParentChanged This function is called when a direct or indirect parent of the transform of the GameObject has changed.
OnTriggerEnter When a GameObject collides with another GameObject, Unity calls OnTriggerEnter.
OnTriggerEnter2D Sent when another object enters a trigger collider attached to this object (2D physics only).
OnTriggerExit OnTriggerExit is called when the Collider other has stopped touching the trigger.
OnTriggerExit2D Sent when another object leaves a trigger collider attached to this object (2D physics only).
OnTriggerStay OnTriggerStay is called once per physics update for every Collider other that is touching the trigger.
OnTriggerStay2D Sent each frame where another object is within a trigger collider attached to this object (2D physics only).
OnValidate Editor-only function that Unity calls when the script is loaded or a value changes in the Inspector.
OnWillRenderObject OnWillRenderObject is called for each camera if the object is visible and not a UI element.
Reset Reset to default values.
Start Start is called on the frame when a script is enabled just before any of the Update methods are called the first time.
Update Update is called every frame, if the MonoBehaviour is enabled.

Inherited Members

Properties

enabled Enabled Behaviours are Updated, disabled Behaviours are not.
isActiveAndEnabled Reports whether a GameObject and its associated Behaviour is active and enabled.
gameObject The game object this component is attached to. A component is always attached to a game object.
tag The tag of this game object.
transform The Transform attached to this GameObject.
hideFlags Should the object be hidden, saved with the Scene or modifiable by the user?
name The name of the object.

Public Methods

BroadcastMessage Calls the method named methodName on every MonoBehaviour in this game object or any of its children.
CompareTag Checks the GameObject’s tag against the defined tag.
GetComponent Returns the component of type if the GameObject has one attached.
GetComponentInChildren Returns the Component of type in the GameObject or any of its children using depth first search.
GetComponentInParent Returns the Component of type in the GameObject or any of its parents.
GetComponents Returns all components of Type type in the GameObject.
GetComponentsInChildren Returns all components of Type type in the GameObject or any of its children using depth first search. Works recursively.
GetComponentsInParent Returns all components of Type type in the GameObject or any of its parents.
SendMessage Calls the method named methodName on every MonoBehaviour in this game object.
SendMessageUpwards Calls the method named methodName on every MonoBehaviour in this game object and on every ancestor of the behaviour.
TryGetComponent Gets the component of the specified type, if it exists.
GetInstanceID Gets the instance ID of the object.
ToString Returns the name of the object.

Static Methods

Destroy Removes a GameObject, component or asset.
DestroyImmediate Destroys the object obj immediately. You are strongly recommended to use Destroy instead.
DontDestroyOnLoad Do not destroy the target Object when loading a new Scene.
FindObjectOfType Returns the first active loaded object of Type type.
FindObjectsOfType Gets a list of all loaded objects of Type type.
Instantiate Clones the object original and returns the clone.

Operators

bool Does the object exist?
operator != Compares if two objects refer to a different object.
operator == Compares two object references to see if they refer to the same object.

Is something described here not working as you expect it to? It might be a Known Issue. Please check with the Issue Tracker at issuetracker.unity3d.com.

Copyright ©2023 Unity Technologies. Publication Date: 2023-01-06.

Источник

// ——————————————————————————————————————— // <copyright file=»NetworkingPeer.cs» company=»Exit Games GmbH»> // Part of: Photon Unity Networking (PUN) // </copyright> // ——————————————————————————————————————— using ExitGames.Client.Photon; using ExitGames.Client.Photon.Lite; using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using UnityEngine; using Hashtable = ExitGames.Client.Photon.Hashtable; /// <summary> /// Implements Photon LoadBalancing used in PUN. /// This class is used internally by PhotonNetwork and not intended as public API. /// </summary> internal class NetworkingPeer : LoadbalancingPeer, IPhotonPeerListener { /// <summary>The GameVersion as set in the Connect-methods.</summary> protected internal string mAppVersion; /// <summary>Combination of GameVersion+»_»+PunVersion. Separates players per app by version.</summary> protected internal string mAppVersionPun { get { return string.Format(«{0}_{1}«, mAppVersion, PhotonNetwork.versionPUN); } } /// <summary>Contains the AppId for the Photon Cloud (ignored by Photon Servers).</summary> protected internal string mAppId; /// <summary> /// A user’s authentication values used during connect for Custom Authentication with Photon (and a custom service/community). /// Set these before calling Connect if you want custom authentication. /// </summary> public AuthenticationValues CustomAuthenticationValues { get; set; } public string MasterServerAddress { get; protected internal set; } private string playername = ««; private IPhotonPeerListener externalListener; private JoinType mLastJoinType; private bool mPlayernameHasToBeUpdated; public string PlayerName { get { return this.playername; } set { if (string.IsNullOrEmpty(value) || value.Equals(this.playername)) { return; } if (this.mLocalActor != null) { this.mLocalActor.name = value; } this.playername = value; if (this.mCurrentGame != null) { // Only when in a room this.SendPlayerName(); } } } public PeerState State { get; internal set; } // «public» access to the current game — is null unless a room is joined on a gameserver public Room mCurrentGame { get { if (this.mRoomToGetInto != null && this.mRoomToGetInto.isLocalClientInside) { return this.mRoomToGetInto; } return null; } } /// <summary> /// keeps the custom properties, gameServer address and anything else about the room we want to get into /// </summary> internal Room mRoomToGetInto { get; set; } internal RoomOptions mRoomOptionsForCreate { get; set; } internal TypedLobby mRoomToEnterLobby { get; set; } public Dictionary<int, PhotonPlayer> mActors = new Dictionary<int, PhotonPlayer>(); public PhotonPlayer[] mOtherPlayerListCopy = new PhotonPlayer[0]; public PhotonPlayer[] mPlayerListCopy = new PhotonPlayer[0]; public PhotonPlayer mLocalActor { get; internal set; } public PhotonPlayer mMasterClient = null; public bool hasSwitchedMC = false; public string mGameserver { get; internal set; } public bool requestSecurity = true; private Dictionary<Type, List<MethodInfo>> monoRPCMethodsCache = new Dictionary<Type, List<MethodInfo>>(); public static bool UsePrefabCache = true; public static Dictionary<string, GameObject> PrefabCache = new Dictionary<string, GameObject>(); public Dictionary<string, RoomInfo> mGameList = new Dictionary<string, RoomInfo>(); public RoomInfo[] mGameListCopy = new RoomInfo[0]; public TypedLobby lobby { get; set; } public bool insideLobby = false; /// <summary>Stat value: Count of players on Master (looking for rooms)</summary> public int mPlayersOnMasterCount { get; internal set; } /// <summary>Stat value: Count of Rooms</summary> public int mGameCount { get; internal set; } /// <summary>Stat value: Count of Players in rooms</summary> public int mPlayersInRoomsCount { get; internal set; } private HashSet<int> allowedReceivingGroups = new HashSet<int>(); private HashSet<int> blockSendingGroups = new HashSet<int>(); internal protected Dictionary<int, PhotonView> photonViewList = new Dictionary<int, PhotonView>(); //TODO: make private again private readonly Dictionary<int, Hashtable> dataPerGroupReliable = new Dictionary<int, Hashtable>(); // only used in RunViewUpdate() private readonly Dictionary<int, Hashtable> dataPerGroupUnreliable = new Dictionary<int, Hashtable>(); // only used in RunViewUpdate() internal protected short currentLevelPrefix = 0; private readonly Dictionary<string, int> rpcShortcuts; // lookup «table» for the index (shortcut) of an RPC name /// <summary>The server this client is currently connected or connecting to.</summary> internal protected ServerConnection server { get; private set; } public bool IsInitialConnect = false; /// <summary>True if this client uses a NameServer to get the Master Server address.</summary> public bool IsUsingNameServer { get; protected internal set; } /// <summary>Name Server Address that this client uses. You can use the default values and usually won’t have to set this value.</summary> public string NameServerAddress = «ns.exitgamescloud.com«; public string NameServerAddressHttp = «http://ns.exitgamescloud.com:80/photon/n«; private static readonly Dictionary<ConnectionProtocol, int> ProtocolToNameServerPort = new Dictionary<ConnectionProtocol, int>() { {ConnectionProtocol.Udp, 5058}, {ConnectionProtocol.Tcp, 4533} }; //, { ConnectionProtocol.RHttp, 6063 } }; /// <summary>A list of region names for the Photon Cloud. Set by the result of OpGetRegions().</summary> /// <remarks>Put a «case OperationCode.GetRegions:» into your OnOperationResponse method to notice when the result is available.</remarks> public List<Region> AvailableRegions { get; protected internal set; } /// <summary>The cloud region this client connects to. Set by ConnectToRegionMaster().</summary> public CloudRegionCode CloudRegion { get; protected internal set; } /// <summary>Internally used to check if a «Secret» is available to use. Sent by Photon Cloud servers, it simplifies authentication when switching servers.</summary> public bool IsAuthorizeSecretAvailable { get { // TODO: comment in the code again, when the new auth-workflow is available in the Cloud return false; // this.CustomAuthenticationValues != null && !String.IsNullOrEmpty(this.CustomAuthenticationValues.Secret); } } /// <summary>Internally used to trigger OpAuthenticate when encryption was established after a connect.</summary> private bool didAuthenticate; public NetworkingPeer(IPhotonPeerListener listener, string playername, ConnectionProtocol connectionProtocol) : base(listener, connectionProtocol) { #if !UNITY_EDITOR && (UNITY_WINRT) // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor) Debug.LogWarning(«Using PingWindowsStore«); PhotonHandler.PingImplementation = typeof(PingWindowsStore); // but for ping, we have to set the implementation explicitly to Win 8 Store/Phone #endif #pragma warning disable 0162 // the library variant defines if we should use PUN’s SocketUdp variant (at all) if (PhotonPeer.NoSocket) { #if !UNITY_EDITOR && (UNITY_PS3 || UNITY_ANDROID) Debug.Log(«Using class SocketUdpNativeDynamic«); this.SocketImplementation = typeof(SocketUdpNativeDynamic); PhotonHandler.PingImplementation = typeof(PingNativeDynamic); #elif !UNITY_EDITOR && UNITY_IPHONE Debug.Log(«Using class SocketUdpNativeStatic«); this.SocketImplementation = typeof(SocketUdpNativeStatic); PhotonHandler.PingImplementation = typeof(PingNativeStatic); #elif !UNITY_EDITOR && (UNITY_WINRT) // this automatically uses a separate assembly-file with Win8-style Socket usage (not possible in Editor) #else this.SocketImplementation = typeof (SocketUdp); PhotonHandler.PingImplementation = typeof(PingMonoEditor); #endif if (this.SocketImplementation == null) { Debug.Log(«No socket implementation set for ‘NoSocket’ assembly. Please contact Exit Games.«); } } #pragma warning restore 0162 if (PhotonHandler.PingImplementation == null) { PhotonHandler.PingImplementation = typeof(PingMono); } this.Listener = this; this.lobby = TypedLobby.Default; this.LimitOfUnreliableCommands = 40; // don’t set the field directly! the listener is passed on to other classes, which get updated by the property set method this.externalListener = listener; this.PlayerName = playername; this.mLocalActor = new PhotonPlayer(true, 1, this.playername); this.AddNewPlayer(this.mLocalActor.ID, this.mLocalActor); // RPC shortcut lookup creation (from list of RPCs, which is updated by Editor scripts) rpcShortcuts = new Dictionary<string, int>(PhotonNetwork.PhotonServerSettings.RpcList.Count); for (int index = 0; index < PhotonNetwork.PhotonServerSettings.RpcList.Count; index++) { var name = PhotonNetwork.PhotonServerSettings.RpcList[index]; rpcShortcuts[name] = index; } this.State = global::PeerState.PeerCreated; } #region Operations and Connection Methods public override bool Connect(string serverAddress, string applicationName) { Debug.LogError(«Avoid using this directly. Thanks.«); return false; } public bool Connect(string serverAddress, ServerConnection type) { if (PhotonHandler.AppQuits) { Debug.LogWarning(«Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits.«); return false; } if (PhotonNetwork.connectionStateDetailed == global::PeerState.Disconnecting) { Debug.LogError(«Connect() failed. Can’t connect while disconnecting (still). Current state: « + PhotonNetwork.connectionStateDetailed); return false; } // connect might fail, if the DNS name can’t be resolved or if no network connection is available bool connecting = base.Connect(serverAddress, ««); if (connecting) { switch (type) { case ServerConnection.NameServer: State = global::PeerState.ConnectingToNameServer; break; case ServerConnection.MasterServer: State = global::PeerState.ConnectingToMasterserver; break; case ServerConnection.GameServer: State = global::PeerState.ConnectingToGameserver; break; } } return connecting; } /// <summary> /// Connects to the NameServer for Photon Cloud, where a region and server list can be obtained. /// </summary> /// <see cref=«OpGetRegions«/> /// <returns>If the workflow was started or failed right away.</returns> public bool ConnectToNameServer() { if (PhotonHandler.AppQuits) { Debug.LogWarning(«Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits.«); return false; } IsUsingNameServer = true; this.CloudRegion = CloudRegionCode.none; if (this.State == global::PeerState.ConnectedToNameServer) { return true; } #if RHTTP string address = (this.UsedProtocol == ConnectionProtocol.RHttp) ? this.NameServerAddressHttp : this.NameServerAddress; #else string address = this.NameServerAddress; #endif if (!address.Contains(«:«)) { int port = 0; ProtocolToNameServerPort.TryGetValue(this.UsedProtocol, out port); address = string.Format(«{0}:{1}«, address, port); Debug.Log(«Server to connect to: « + address + « settings protocol: « + PhotonNetwork.PhotonServerSettings.Protocol); } if (!base.Connect(address, «ns«)) { return false; } this.State = global::PeerState.ConnectingToNameServer; return true; } /// <summary> /// Connects you to a specific region’s Master Server, using the Name Server to find the IP. /// </summary> /// <returns>If the operation could be sent. If false, no operation was sent.</returns> public bool ConnectToRegionMaster(CloudRegionCode region) { if (PhotonHandler.AppQuits) { Debug.LogWarning(«Ignoring Connect() because app gets closed. If this is an error, check PhotonHandler.AppQuits.«); return false; } IsUsingNameServer = true; this.CloudRegion = region; if (this.State == global::PeerState.ConnectedToNameServer) { return this.OpAuthenticate(this.mAppId, this.mAppVersionPun, this.PlayerName, this.CustomAuthenticationValues, region.ToString()); } #if RHTTP string address = (this.UsedProtocol == ConnectionProtocol.RHttp) ? this.NameServerAddressHttp : this.NameServerAddress; #else string address = this.NameServerAddress; #endif if (!address.Contains(«:«)) { int port = 0; ProtocolToNameServerPort.TryGetValue(this.UsedProtocol, out port); address = string.Format(«{0}:{1}«, address, port); //Debug.Log(«Server to connect to: «+ address + » settings protocol: » + PhotonNetwork.PhotonServerSettings.Protocol); } if (!base.Connect(address, «ns«)) { return false; } this.State = global::PeerState.ConnectingToNameServer; return true; } /// <summary> /// While on the NameServer, this gets you the list of regional servers (short names and their IPs to ping them). /// </summary> /// <returns>If the operation could be sent. If false, no operation was sent (e.g. while not connected to the NameServer).</returns> public bool GetRegions() { if (this.server != ServerConnection.NameServer) { return false; } bool sent = this.OpGetRegions(this.mAppId); if (sent) { this.AvailableRegions = null; } return sent; } /// <summary> /// Complete disconnect from photon (and the open master OR game server) /// </summary> public override void Disconnect() { if (this.PeerState == PeerStateValue.Disconnected) { if (!PhotonHandler.AppQuits) { Debug.LogWarning(string.Format(«Can’t execute Disconnect() while not connected. Nothing changed. State: {0}«, this.State)); } return; } this.State = global::PeerState.Disconnecting; base.Disconnect(); //this.LeftRoomCleanup(); //this.LeftLobbyCleanup(); } /// <summary> /// Internally used only. Triggers OnStateChange with «Disconnect» in next dispatch which is the signal to re-connect (if at all). /// </summary> private void DisconnectToReconnect() { switch (this.server) { case ServerConnection.NameServer: this.State = global::PeerState.DisconnectingFromNameServer; base.Disconnect(); break; case ServerConnection.MasterServer: this.State = global::PeerState.DisconnectingFromMasterserver; base.Disconnect(); //LeftLobbyCleanup(); break; case ServerConnection.GameServer: this.State = global::PeerState.DisconnectingFromGameserver; base.Disconnect(); //this.LeftRoomCleanup(); break; } } /// <summary> /// Called at disconnect/leavelobby etc. This CAN also be called when we are not in a lobby (e.g. disconnect from room) /// </summary> /// <remarks>Calls callback method OnLeftLobby if this client was in a lobby initially. Clears the lobby’s game lists.</remarks> private void LeftLobbyCleanup() { this.mGameList = new Dictionary<string, RoomInfo>(); this.mGameListCopy = new RoomInfo[0]; if (insideLobby) { this.insideLobby = false; SendMonoMessage(PhotonNetworkingMessage.OnLeftLobby); } } /// <summary> /// Called when «this client» left a room to clean up. /// </summary> private void LeftRoomCleanup() { bool wasInRoom = mRoomToGetInto != null; // when leaving a room, we clean up depending on that room’s settings. bool autoCleanupSettingOfRoom = (this.mRoomToGetInto != null) ? this.mRoomToGetInto.autoCleanUp : PhotonNetwork.autoCleanUpPlayerObjects; this.hasSwitchedMC = false; this.mRoomToGetInto = null; this.mActors = new Dictionary<int, PhotonPlayer>(); this.mPlayerListCopy = new PhotonPlayer[0]; this.mOtherPlayerListCopy = new PhotonPlayer[0]; this.mMasterClient = null; this.allowedReceivingGroups = new HashSet<int>(); this.blockSendingGroups = new HashSet<int>(); this.mGameList = new Dictionary<string, RoomInfo>(); this.mGameListCopy = new RoomInfo[0]; this.isFetchingFriends = false; this.ChangeLocalID(1); // Cleanup all network objects (all spawned PhotonViews, local and remote) if (autoCleanupSettingOfRoom) { this.LocalCleanupAnythingInstantiated(true); PhotonNetwork.manuallyAllocatedViewIds = new List<int>(); // filled and easier to replace completely } if (wasInRoom) { SendMonoMessage(PhotonNetworkingMessage.OnLeftRoom); } } /// <summary> /// Cleans up anything that was instantiated in-game (not loaded with the scene). /// </summary> protected internal void LocalCleanupAnythingInstantiated(bool destroyInstantiatedGameObjects) { if (tempInstantiationData.Count > 0) { Debug.LogWarning(«It seems some instantiation is not completed, as instantiation data is used. You should make sure instantiations are paused when calling this method. Cleaning now, despite this.«); } // Destroy GO’s (if we should) if (destroyInstantiatedGameObjects) { // Fill list with Instantiated objects HashSet<GameObject> instantiatedGos = new HashSet<GameObject>(); foreach (PhotonView view in this.photonViewList.Values) { if (view.isRuntimeInstantiated) { instantiatedGos.Add(view.gameObject); // HashSet keeps each object only once } } foreach (GameObject go in instantiatedGos) { this.RemoveInstantiatedGO(go, true); } } // photonViewList is cleared of anything instantiated (so scene items are left inside) // any other lists can be this.tempInstantiationData.Clear(); // should be empty but to be safe we clear (no new list needed) PhotonNetwork.lastUsedViewSubId = 0; PhotonNetwork.lastUsedViewSubIdStatic = 0; } // gameID can be null (optional). The server assigns a unique name if no name is set // joins a room and sets your current username as custom actorproperty (will broadcast that) #endregion #region Helpers private void ReadoutProperties(Hashtable gameProperties, Hashtable pActorProperties, int targetActorNr) { // Debug.LogWarning(«ReadoutProperties gameProperties: » + gameProperties.ToStringFull() + » pActorProperties: » + pActorProperties.ToStringFull() + » targetActorNr: » + targetActorNr); // read game properties and cache them locally if (this.mCurrentGame != null && gameProperties != null) { this.mCurrentGame.CacheProperties(gameProperties); SendMonoMessage(PhotonNetworkingMessage.OnPhotonCustomRoomPropertiesChanged, gameProperties); if (PhotonNetwork.automaticallySyncScene) { this.LoadLevelIfSynced(); // will load new scene if sceneName was changed } } if (pActorProperties != null && pActorProperties.Count > 0) { if (targetActorNr > 0) { // we have a single entry in the pActorProperties with one // user’s name // targets MUST exist before you set properties PhotonPlayer target = this.GetPlayerWithID(targetActorNr); if (target != null) { Hashtable props = this.GetActorPropertiesForActorNr(pActorProperties, targetActorNr); target.InternalCacheProperties(props); SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props); } } else { // in this case, we’ve got a key-value pair per actor (each // value is a hashtable with the actor’s properties then) int actorNr; Hashtable props; string newName; PhotonPlayer target; foreach (object key in pActorProperties.Keys) { actorNr = (int)key; props = (Hashtable)pActorProperties[key]; newName = (string)props[ActorProperties.PlayerName]; target = this.GetPlayerWithID(actorNr); if (target == null) { target = new PhotonPlayer(false, actorNr, newName); this.AddNewPlayer(actorNr, target); } target.InternalCacheProperties(props); SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props); } } } } private void AddNewPlayer(int ID, PhotonPlayer player) { if (!this.mActors.ContainsKey(ID)) { this.mActors[ID] = player; RebuildPlayerListCopies(); } else { Debug.LogError(«Adding player twice: « + ID); } } void RemovePlayer(int ID, PhotonPlayer player) { this.mActors.Remove(ID); if (!player.isLocal) { RebuildPlayerListCopies(); } } void RebuildPlayerListCopies() { this.mPlayerListCopy = new PhotonPlayer[this.mActors.Count]; this.mActors.Values.CopyTo(this.mPlayerListCopy, 0); List<PhotonPlayer> otherP = new List<PhotonPlayer>(); foreach (PhotonPlayer player in this.mPlayerListCopy) { if (!player.isLocal) { otherP.Add(player); } } this.mOtherPlayerListCopy = otherP.ToArray(); } /// <summary> /// Resets the PhotonView «lastOnSerializeDataSent» so that «OnReliable» synched PhotonViews send a complete state to new clients (if the state doesnt change, no messages would be send otherwise!). /// Note that due to this reset, ALL other players will receive the full OnSerialize. /// </summary> private void ResetPhotonViewsOnSerialize() { foreach (PhotonView photonView in this.photonViewList.Values) { photonView.lastOnSerializeDataSent = null; } } /// <summary> /// Called when the event Leave (of some other player) arrived. /// Cleans game objects, views locally. The master will also clean the /// </summary> /// <param name=«actorID«>ID of player who left.</param> private void HandleEventLeave(int actorID) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(«HandleEventLeave for player ID: « + actorID); // actorNr is fetched out of event above if (actorID < 0 || !this.mActors.ContainsKey(actorID)) { Debug.LogError(String.Format(«Received event Leave for unknown player ID: {0}«, actorID)); return; } PhotonPlayer player = this.GetPlayerWithID(actorID); if (player == null) { Debug.LogError(«HandleEventLeave for player ID: « + actorID + « has no PhotonPlayer!«); } // having a new master before calling destroy for the leaving player is important! // so we elect a new masterclient and ignore the leaving player (who is still in playerlists). this.CheckMasterClient(actorID); // destroy objects & buffered messages if (this.mCurrentGame != null && this.mCurrentGame.autoCleanUp) { this.DestroyPlayerObjects(actorID, true); } RemovePlayer(actorID, player); // finally, send notification (the playerList and masterclient are now updated) SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerDisconnected, player); } /// <summary>Picks the new master client from player list, if the current Master is leaving (leavingPlayerId) or if no master was assigned so far.</summary> /// <param name=«leavingPlayerId«> /// The ignored player is the one who’s leaving and should not become master (again). Pass -1 to select any player from the list. /// </param> private void CheckMasterClient(int leavingPlayerId) { bool currentMasterIsLeaving = this.mMasterClient != null && this.mMasterClient.ID == leavingPlayerId; bool someoneIsLeaving = leavingPlayerId > 0; // return early if SOME player (leavingId > 0) is leaving AND it’s NOT the current master if (someoneIsLeaving && !currentMasterIsLeaving) { return; } // picking the player with lowest ID (longest in game). if (this.mActors.Count <= 1) { this.mMasterClient = this.mLocalActor; } else { // keys in mActors are their actorNumbers int lowestActorNumber = Int32.MaxValue; foreach (int key in this.mActors.Keys) { if (key < lowestActorNumber && key != leavingPlayerId) { lowestActorNumber = key; } } this.mMasterClient = this.mActors[lowestActorNumber]; } // make a callback ONLY when a player/Master left if (someoneIsLeaving) { SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, this.mMasterClient); } } /// <summary> /// Returns the lowest player.ID — used for Master Client picking. /// </summary> /// <remarks></remarks> private static int ReturnLowestPlayerId(PhotonPlayer[] players, int playerIdToIgnore) { if (players == null || players.Length == 0) { return 1; } int lowestActorNumber = Int32.MaxValue; for (int i = 0; i < players.Length; i++) { PhotonPlayer photonPlayer = players[i]; if (photonPlayer.ID == playerIdToIgnore) { continue; } if (photonPlayer.ID < lowestActorNumber) { lowestActorNumber = photonPlayer.ID; } } return lowestActorNumber; } internal protected bool SetMasterClient(int playerId, bool sync) { bool masterReplaced = this.mMasterClient != null && this.mMasterClient.ID != playerId; if (!masterReplaced || !this.mActors.ContainsKey(playerId)) { return false; } if (sync) { bool sent = this.OpRaiseEvent(PunEvent.AssignMaster, new Hashtable() { { (byte)1, playerId } }, true, null); if (!sent) { return false; } } this.hasSwitchedMC = true; this.mMasterClient = this.mActors[playerId]; SendMonoMessage(PhotonNetworkingMessage.OnMasterClientSwitched, this.mMasterClient); // we only callback when an actual change is done return true; } private Hashtable GetActorPropertiesForActorNr(Hashtable actorProperties, int actorNr) { if (actorProperties.ContainsKey(actorNr)) { return (Hashtable)actorProperties[actorNr]; } return actorProperties; } private PhotonPlayer GetPlayerWithID(int number) { if (this.mActors != null && this.mActors.ContainsKey(number)) { return this.mActors[number]; } return null; } private void SendPlayerName() { if (this.State == global::PeerState.Joining) { // this means, the join on the gameServer is sent (with an outdated name). send the new when in game this.mPlayernameHasToBeUpdated = true; return; } if (this.mLocalActor != null) { this.mLocalActor.name = this.PlayerName; Hashtable properties = new Hashtable(); properties[ActorProperties.PlayerName] = this.PlayerName; if (this.mLocalActor.ID > 0) { this.OpSetPropertiesOfActor(this.mLocalActor.ID, properties, true, (byte)0); this.mPlayernameHasToBeUpdated = false; } } } private void GameEnteredOnGameServer(OperationResponse operationResponse) { if (operationResponse.ReturnCode != 0) { switch (operationResponse.OperationCode) { case OperationCode.CreateGame: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(«Create failed on GameServer. Changing back to MasterServer. Msg: « + operationResponse.DebugMessage); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; case OperationCode.JoinGame: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(«Join failed on GameServer. Changing back to MasterServer. Msg: « + operationResponse.DebugMessage); if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist) { Debug.Log(«Most likely the game became empty during the switch to GameServer.«); } } SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; case OperationCode.JoinRandomGame: if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(«Join failed on GameServer. Changing back to MasterServer. Msg: « + operationResponse.DebugMessage); if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist) { Debug.Log(«Most likely the game became empty during the switch to GameServer.«); } } SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; } this.DisconnectToReconnect(); return; } this.State = global::PeerState.Joined; this.mRoomToGetInto.isLocalClientInside = true; Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties]; Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties]; this.ReadoutProperties(gameProperties, actorProperties, 0); // the local player’s actor-properties are not returned in join-result. add this player to the list int localActorNr = (int)operationResponse[ParameterCode.ActorNr]; this.ChangeLocalID(localActorNr); this.CheckMasterClient(1); if (this.mPlayernameHasToBeUpdated) { this.SendPlayerName(); } switch (operationResponse.OperationCode) { case OperationCode.CreateGame: SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); break; case OperationCode.JoinGame: case OperationCode.JoinRandomGame: // the mono message for this is sent at another place break; } } private Hashtable GetLocalActorProperties() { if (PhotonNetwork.player != null) { return PhotonNetwork.player.allProperties; } Hashtable actorProperties = new Hashtable(); actorProperties[ActorProperties.PlayerName] = this.PlayerName; return actorProperties; } public void ChangeLocalID(int newID) { if (this.mLocalActor == null) { Debug.LogWarning( string.Format( «Local actor is null or not in mActors! mLocalActor: {0} mActors==null: {1} newID: {2}«, this.mLocalActor, this.mActors == null, newID)); } if (this.mActors.ContainsKey(this.mLocalActor.ID)) { this.mActors.Remove(this.mLocalActor.ID); } this.mLocalActor.InternalChangeLocalID(newID); this.mActors[this.mLocalActor.ID] = this.mLocalActor; this.RebuildPlayerListCopies(); } #endregion #region Operations /// <summary>NetworkingPeer.OpCreateGame</summary> public bool OpCreateGame(string roomName, RoomOptions roomOptions, TypedLobby typedLobby) { bool onGameServer = this.server == ServerConnection.GameServer; if (!onGameServer) { this.mRoomOptionsForCreate = roomOptions; this.mRoomToGetInto = new Room(roomName, roomOptions); this.mRoomToEnterLobby = typedLobby ?? ((this.insideLobby) ? this.lobby : null); // use given lobby, or active lobby (if any active) or none } this.mLastJoinType = JoinType.CreateGame; return base.OpCreateRoom(roomName, roomOptions, this.mRoomToEnterLobby, this.GetLocalActorProperties(), onGameServer); } /// <summary>NetworkingPeer.OpJoinRoom</summary> public bool OpJoinRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby, bool createIfNotExists) { bool onGameServer = this.server == ServerConnection.GameServer; if (!onGameServer) { // roomOptions and typedLobby will be null, unless createIfNotExists is true this.mRoomOptionsForCreate = roomOptions; this.mRoomToGetInto = new Room(roomName, roomOptions); this.mRoomToEnterLobby = null; if (createIfNotExists) { this.mRoomToEnterLobby = typedLobby ?? ((this.insideLobby) ? this.lobby : null); // use given lobby, or active lobby (if any active) or none } } this.mLastJoinType = (createIfNotExists) ? JoinType.JoinOrCreateOnDemand : JoinType.JoinGame; return base.OpJoinRoom(roomName, roomOptions, this.mRoomToEnterLobby, createIfNotExists, this.GetLocalActorProperties(), onGameServer); } /// <summary>NetworkingPeer.OpJoinRandomRoom</summary> /// <remarks>this override just makes sure we have a mRoomToGetInto, even if it’s blank (the properties provided in this method are filters. they are not set when we join the game)</remarks> public override bool OpJoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, Hashtable playerProperties, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter) { this.mRoomToGetInto = new Room(null, null); this.mRoomToEnterLobby = null; // join random never stores the lobby. the following join will not affect the room lobby // if typedLobby is null, the server will automatically use the active lobby or default, which is what we want anyways this.mLastJoinType = JoinType.JoinRandomGame; return base.OpJoinRandomRoom(expectedCustomRoomProperties, expectedMaxPlayers, playerProperties, matchingType, typedLobby, sqlLobbyFilter); } /// <summary> /// Operation Leave will exit any current room. /// </summary> /// <remarks> /// This also happens when you disconnect from the server. /// Disconnect might be a step less if you don’t want to create a new room on the same server. /// </remarks> /// <returns></returns> public virtual bool OpLeave() { if (this.State != global::PeerState.Joined) { Debug.LogWarning(«Not sending leave operation. State is not ‘Joined’: « + this.State); return false; } return this.OpCustom((byte)OperationCode.Leave, null, true, 0); } public override bool OpRaiseEvent(byte eventCode, object customEventContent, bool sendReliable, RaiseEventOptions raiseEventOptions) { if (PhotonNetwork.offlineMode) { return false; } return base.OpRaiseEvent(eventCode, customEventContent, sendReliable, raiseEventOptions); } #endregion #region Implementation of IPhotonPeerListener public void DebugReturn(DebugLevel level, string message) { this.externalListener.DebugReturn(level, message); } public void OnOperationResponse(OperationResponse operationResponse) { if (PhotonNetwork.networkingPeer.State == global::PeerState.Disconnecting) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.Log(«OperationResponse ignored while disconnecting. Code: « + operationResponse.OperationCode); } return; } // extra logging for error debugging (helping developers with a bit of automated analysis) if (operationResponse.ReturnCode == 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(operationResponse.ToString()); } else { if (operationResponse.ReturnCode == ErrorCode.OperationNotAllowedInCurrentState) { Debug.LogError(«Operation « + operationResponse.OperationCode + « could not be executed (yet). Wait for state JoinedLobby or ConnectedToMaster and their callbacks before calling operations. WebRPCs need a server-side configuration. Enum OperationCode helps identify the operation.«); } else if (operationResponse.ReturnCode == ErrorCode.WebHookCallFailed) { Debug.LogError(«Operation « + operationResponse.OperationCode + « failed in a server-side plugin. Check the configuration in the Dashboard. Message from server-plugin: « + operationResponse.DebugMessage); } else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogError(«Operation failed: « + operationResponse.ToStringFull() + « Server: « + this.server); } } // use the «secret» or «token» whenever we get it. doesn’t really matter if it’s in AuthResponse. if (operationResponse.Parameters.ContainsKey(ParameterCode.Secret)) { if (this.CustomAuthenticationValues == null) { this.CustomAuthenticationValues = new AuthenticationValues(); // this.DebugReturn(DebugLevel.ERROR, «Server returned secret. Created CustomAuthenticationValues.»); } this.CustomAuthenticationValues.Secret = operationResponse[ParameterCode.Secret] as string; } switch (operationResponse.OperationCode) { case OperationCode.Authenticate: { // PeerState oldState = this.State; if (operationResponse.ReturnCode != 0) { if (operationResponse.ReturnCode == ErrorCode.InvalidOperationCode) { Debug.LogError(string.Format(«If you host Photon yourself, make sure to start the ‘Instance LoadBalancing’ «+ this.ServerAddress)); } else if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication) { Debug.LogError(string.Format(«The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.«)); SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); } else if (operationResponse.ReturnCode == ErrorCode.CustomAuthenticationFailed) { Debug.LogError(string.Format(«Custom Authentication failed (either due to user-input or configuration or AuthParameter string format). Calling: OnCustomAuthenticationFailed()«)); SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationFailed, operationResponse.DebugMessage); } else { Debug.LogError(string.Format(«Authentication failed: ‘{0}’ Code: {1}«, operationResponse.DebugMessage, operationResponse.ReturnCode)); } this.State = global::PeerState.Disconnecting; this.Disconnect(); if (operationResponse.ReturnCode == ErrorCode.MaxCcuReached) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.LogWarning(string.Format(«Currently, the limit of users is reached for this title. Try again later. Disconnecting«)); SendMonoMessage(PhotonNetworkingMessage.OnPhotonMaxCccuReached); SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.MaxCcuReached); } else if (operationResponse.ReturnCode == ErrorCode.InvalidRegion) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.LogError(string.Format(«The used master server address is not available with the subscription currently used. Got to Photon Cloud Dashboard or change URL. Disconnecting.«)); SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.InvalidRegion); } else if (operationResponse.ReturnCode == ErrorCode.AuthenticationTicketExpired) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.LogError(string.Format(«The authentication ticket expired. You need to connect (and authenticate) again. Disconnecting.«)); SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.AuthenticationTicketExpired); } break; } else { if (this.server == ServerConnection.NameServer) { // on the NameServer, authenticate returns the MasterServer address for a region and we hop off to there this.MasterServerAddress = operationResponse[ParameterCode.Address] as string; this.DisconnectToReconnect(); } else if (this.server == ServerConnection.MasterServer) { if (PhotonNetwork.autoJoinLobby) { this.State = global::PeerState.Authenticated; this.OpJoinLobby(this.lobby); } else { this.State = global::PeerState.ConnectedToMaster; NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster); } } else if (this.server == ServerConnection.GameServer) { this.State = global::PeerState.Joining; if (this.mLastJoinType == JoinType.JoinGame || this.mLastJoinType == JoinType.JoinRandomGame || this.mLastJoinType == JoinType.JoinOrCreateOnDemand) { // if we just «join» the game, do so. if we wanted to «create the room on demand», we have to send this to the game server as well. this.OpJoinRoom(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby, this.mLastJoinType == JoinType.JoinOrCreateOnDemand); } else if (this.mLastJoinType == JoinType.CreateGame) { // on the game server, we have to apply the room properties that were chosen for creation of the room, so we use this.mRoomToGetInto this.OpCreateGame(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby); } break; } } break; } case OperationCode.GetRegions: // Debug.Log(«GetRegions returned: » + operationResponse.ToStringFull()); if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication) { Debug.LogError(string.Format(«The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account.«)); SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication); this.State = global::PeerState.Disconnecting; this.Disconnect(); return; } string[] regions = operationResponse[ParameterCode.Region] as string[]; string[] servers = operationResponse[ParameterCode.Address] as string[]; if (regions == null || servers == null || regions.Length != servers.Length) { Debug.LogError(«The region arrays from Name Server are not ok. Must be non-null and same length.«); break; } this.AvailableRegions = new List<Region>(regions.Length); for (int i = 0; i < regions.Length; i++) { string regionCodeString = regions[i]; if (string.IsNullOrEmpty(regionCodeString)) { continue; } regionCodeString = regionCodeString.ToLower(); CloudRegionCode code = Region.Parse(regionCodeString); this.AvailableRegions.Add(new Region() { Code = code, HostAndPort = servers[i] }); } // PUN assumes you fetch the name-server’s list of regions to ping them if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion) { PhotonHandler.PingAvailableRegionsAndConnectToBest(); } break; case OperationCode.CreateGame: { if (this.server == ServerConnection.GameServer) { this.GameEnteredOnGameServer(operationResponse); } else { if (operationResponse.ReturnCode != 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.LogWarning(string.Format(«CreateRoom failed, client stays on masterserver: {0}.«, operationResponse.ToStringFull())); SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed); break; } string gameID = (string) operationResponse[ParameterCode.RoomName]; if (!string.IsNullOrEmpty(gameID)) { // is only sent by the server’s response, if it has not been // sent with the client’s request before! this.mRoomToGetInto.name = gameID; } this.mGameserver = (string)operationResponse[ParameterCode.Address]; this.DisconnectToReconnect(); } break; } case OperationCode.JoinGame: { if (this.server != ServerConnection.GameServer) { if (operationResponse.ReturnCode != 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(string.Format(«JoinRoom failed (room maybe closed by now). Client stays on masterserver: {0}. State: {1}«, operationResponse.ToStringFull(), this.State)); SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed); break; } this.mGameserver = (string)operationResponse[ParameterCode.Address]; this.DisconnectToReconnect(); } else { this.GameEnteredOnGameServer(operationResponse); } break; } case OperationCode.JoinRandomGame: { // happens only on master. on gameserver, this is a regular join (we don’t need to find a random game again) // the operation OpJoinRandom either fails (with returncode 8) or returns game-to-join information if (operationResponse.ReturnCode != 0) { if (operationResponse.ReturnCode == ErrorCode.NoRandomMatchFound) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«JoinRandom failed: No open game. Calling: OnPhotonRandomJoinFailed() and staying on master server.«); } else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) { Debug.LogWarning(string.Format(«JoinRandom failed: {0}.«, operationResponse.ToStringFull())); } SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage); break; } string roomName = (string)operationResponse[ParameterCode.RoomName]; this.mRoomToGetInto.name = roomName; this.mGameserver = (string)operationResponse[ParameterCode.Address]; this.DisconnectToReconnect(); break; } case OperationCode.JoinLobby: this.State = global::PeerState.JoinedLobby; this.insideLobby = true; SendMonoMessage(PhotonNetworkingMessage.OnJoinedLobby); // this.mListener.joinLobbyReturn(); break; case OperationCode.LeaveLobby: this.State = global::PeerState.Authenticated; this.LeftLobbyCleanup(); // will set insideLobby = false break; case OperationCode.Leave: this.DisconnectToReconnect(); break; case OperationCode.SetProperties: // this.mListener.setPropertiesReturn(returnCode, debugMsg); break; case OperationCode.GetProperties: { Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties]; Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties]; this.ReadoutProperties(gameProperties, actorProperties, 0); // RemoveByteTypedPropertyKeys(actorProperties, false); // RemoveByteTypedPropertyKeys(gameProperties, false); // this.mListener.getPropertiesReturn(gameProperties, actorProperties, returnCode, debugMsg); break; } case OperationCode.RaiseEvent: // this usually doesn’t give us a result. only if the caching is affected the server will send one. break; case OperationCode.FindFriends: bool[] onlineList = operationResponse[ParameterCode.FindFriendsResponseOnlineList] as bool[]; string[] roomList = operationResponse[ParameterCode.FindFriendsResponseRoomIdList] as string[]; if (onlineList != null && roomList != null && this.friendListRequested != null && onlineList.Length == this.friendListRequested.Length) { List<FriendInfo> friendList = new List<FriendInfo>(this.friendListRequested.Length); for (int index = 0; index < this.friendListRequested.Length; index++) { FriendInfo friend = new FriendInfo(); friend.Name = this.friendListRequested[index]; friend.Room = roomList[index]; friend.IsOnline = onlineList[index]; friendList.Insert(index, friend); } PhotonNetwork.Friends = friendList; } else { // any of the lists is null and shouldn’t. print a error Debug.LogError(«FindFriends failed to apply the result, as a required value wasn’t provided or the friend list length differed from result.«); } this.friendListRequested = null; this.isFetchingFriends = false; this.friendListTimestamp = Environment.TickCount; if (this.friendListTimestamp == 0) { this.friendListTimestamp = 1; // makes sure the timestamp is not accidentally 0 } SendMonoMessage(PhotonNetworkingMessage.OnUpdatedFriendList); break; case OperationCode.WebRpc: SendMonoMessage(PhotonNetworkingMessage.OnWebRpcResponse, operationResponse); break; default: Debug.LogWarning(string.Format(«OperationResponse unhandled: {0}«, operationResponse.ToString())); break; } this.externalListener.OnOperationResponse(operationResponse); } /// <summary>Contains the list of names of friends to look up their state on the server.</summary> private string[] friendListRequested; /// <summary> /// Age of friend list info (in milliseconds). It’s 0 until a friend list is fetched. /// </summary> protected internal int FriendsListAge { get { return (this.isFetchingFriends || this.friendListTimestamp == 0) ? 0 : Environment.TickCount this.friendListTimestamp; } } private int friendListTimestamp; /// <summary>Internal flag to know if the client currently fetches a friend list.</summary> private bool isFetchingFriends; /// <summary> /// Request the rooms and online status for a list of friends. All client must set a unique username via PlayerName property. The result is available in this.Friends. /// </summary> /// <remarks> /// Used on Master Server to find the rooms played by a selected list of users. /// The result will be mapped to LoadBalancingClient.Friends when available. /// The list is initialized by OpFindFriends on first use (before that, it is null). /// /// Users identify themselves by setting a PlayerName in the LoadBalancingClient instance. /// This in turn will send the name in OpAuthenticate after each connect (to master and game servers). /// Note: Changing a player’s name doesn’t make sense when using a friend list. /// /// The list of usernames must be fetched from some other source (not provided by Photon). /// /// /// Internal: /// The server response includes 2 arrays of info (each index matching a friend from the request): /// ParameterCode.FindFriendsResponseOnlineList = bool[] of online states /// ParameterCode.FindFriendsResponseRoomIdList = string[] of room names (empty string if not in a room) /// </remarks> /// <param name=«friendsToFind«>Array of friend’s names (make sure they are unique).</param> /// <returns>If the operation could be sent (requires connection, only one request is allowed at any time). Always false in offline mode.</returns> public override bool OpFindFriends(string[] friendsToFind) { if (this.isFetchingFriends) { return false; // fetching friends currently, so don’t do it again (avoid changing the list while fetching friends) } this.friendListRequested = friendsToFind; this.isFetchingFriends = true; return base.OpFindFriends(friendsToFind); } public void OnStatusChanged(StatusCode statusCode) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(string.Format(«OnStatusChanged: {0}«, statusCode.ToString())); switch (statusCode) { case StatusCode.Connect: if (this.State == global::PeerState.ConnectingToNameServer) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Connected to NameServer.«); this.server = ServerConnection.NameServer; if (this.CustomAuthenticationValues != null) { this.CustomAuthenticationValues.Secret = null; // when connecting to NameServer, invalidate any auth values } } if (this.State == global::PeerState.ConnectingToGameserver) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Connected to gameserver.«); this.server = ServerConnection.GameServer; this.State = global::PeerState.ConnectedToGameserver; } if (this.State == global::PeerState.ConnectingToMasterserver) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Connected to masterserver.«); this.server = ServerConnection.MasterServer; this.State = global::PeerState.ConnectedToMaster; if (this.IsInitialConnect) { this.IsInitialConnect = false; // after handling potential initial-connect issues with special messages, we are now sure we can reach a server SendMonoMessage(PhotonNetworkingMessage.OnConnectedToPhoton); } } this.EstablishEncryption(); // always enable encryption if (this.IsAuthorizeSecretAvailable) { // if we have a token we don’t have to wait for encryption (it is encrypted anyways, so encryption is just optional later on) this.didAuthenticate = this.OpAuthenticate(this.mAppId, this.mAppVersionPun, this.PlayerName, this.CustomAuthenticationValues, this.CloudRegion.ToString()); if (this.didAuthenticate) { this.State = global::PeerState.Authenticating; } } break; case StatusCode.EncryptionEstablished: // on nameserver, the «process» is stopped here, so the developer/game can either get regions or authenticate with a specific region if (this.server == ServerConnection.NameServer) { this.State = global::PeerState.ConnectedToNameServer; if (!this.didAuthenticate && this.CloudRegion == CloudRegionCode.none) { // this client is not setup to connect to a default region. find out which regions there are! this.OpGetRegions(this.mAppId); } } // we might need to authenticate automatically now, so the client can do anything at all if (!this.didAuthenticate && (!this.IsUsingNameServer || this.CloudRegion != CloudRegionCode.none)) { // once encryption is availble, the client should send one (secure) authenticate. it includes the AppId (which identifies your app on the Photon Cloud) this.didAuthenticate = this.OpAuthenticate(this.mAppId, this.mAppVersionPun, this.PlayerName, this.CustomAuthenticationValues, this.CloudRegion.ToString()); if (this.didAuthenticate) { this.State = global::PeerState.Authenticating; } } break; case StatusCode.EncryptionFailedToEstablish: Debug.LogError(«Encryption wasn’t established: « + statusCode + «. Going to authenticate anyways.«); this.OpAuthenticate(this.mAppId, this.mAppVersionPun, this.PlayerName, this.CustomAuthenticationValues, this.CloudRegion.ToString()); // TODO: check if there are alternatives break; case StatusCode.Disconnect: this.didAuthenticate = false; this.isFetchingFriends = false; if (server == ServerConnection.GameServer) this.LeftRoomCleanup(); if (server == ServerConnection.MasterServer) this.LeftLobbyCleanup(); if (this.State == global::PeerState.DisconnectingFromMasterserver) { if (this.Connect(this.mGameserver, ServerConnection.GameServer)) { this.State = global::PeerState.ConnectingToGameserver; } } else if (this.State == global::PeerState.DisconnectingFromGameserver || this.State == global::PeerState.DisconnectingFromNameServer) { if (this.Connect(this.MasterServerAddress, ServerConnection.MasterServer)) { this.State = global::PeerState.ConnectingToMasterserver; } } else { if (this.CustomAuthenticationValues != null) { this.CustomAuthenticationValues.Secret = null; // invalidate any custom auth secrets } this.State = global::PeerState.PeerCreated; // if we set another state here, we could keep clients from connecting in OnDisconnectedFromPhoton right here. SendMonoMessage(PhotonNetworkingMessage.OnDisconnectedFromPhoton); } break; case StatusCode.SecurityExceptionOnConnect: case StatusCode.ExceptionOnConnect: this.State = global::PeerState.PeerCreated; if (this.CustomAuthenticationValues != null) { this.CustomAuthenticationValues.Secret = null; // invalidate any custom auth secrets } DisconnectCause cause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); break; case StatusCode.Exception: if (this.IsInitialConnect) { Debug.LogError(«Exception while connecting to: « + this.ServerAddress + «. Check if the server is available.«); if (this.ServerAddress == null || this.ServerAddress.StartsWith(«127.0.0.1«)) { Debug.LogWarning(«The server address is 127.0.0.1 (localhost): Make sure the server is running on this machine. Android and iOS emulators have their own localhost.«); if (this.ServerAddress == this.mGameserver) { Debug.LogWarning(«This might be a misconfiguration in the game server config. You need to edit it to a (public) address.«); } } this.State = global::PeerState.PeerCreated; cause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); } else { this.State = global::PeerState.PeerCreated; cause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, cause); } this.Disconnect(); break; case StatusCode.TimeoutDisconnect: case StatusCode.ExceptionOnReceive: case StatusCode.DisconnectByServer: case StatusCode.DisconnectByServerLogic: case StatusCode.DisconnectByServerUserLimit: if (this.IsInitialConnect) { Debug.LogWarning(statusCode + « while connecting to: « + this.ServerAddress + «. Check if the server is available.«); cause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, cause); } else { cause = (DisconnectCause)statusCode; SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, cause); } if (this.CustomAuthenticationValues != null) { this.CustomAuthenticationValues.Secret = null; // invalidate any custom auth secrets } this.Disconnect(); break; case StatusCode.SendError: // this.mListener.clientErrorReturn(statusCode); break; case StatusCode.QueueOutgoingReliableWarning: case StatusCode.QueueOutgoingUnreliableWarning: case StatusCode.QueueOutgoingAcksWarning: case StatusCode.QueueSentWarning: // this.mListener.warningReturn(statusCode); break; case StatusCode.QueueIncomingReliableWarning: case StatusCode.QueueIncomingUnreliableWarning: Debug.Log(statusCode + «. This client buffers many incoming messages. This is OK temporarily. With lots of these warnings, check if you send too much or execute messages too slow. « + (PhotonNetwork.isMessageQueueRunning? ««:«Your isMessageQueueRunning is false. This can cause the issue temporarily.«) ); break; // // TCP «routing» is an option of Photon that’s not currently needed (or supported) by PUN //case StatusCode.TcpRouterResponseOk: // break; //case StatusCode.TcpRouterResponseEndpointUnknown: //case StatusCode.TcpRouterResponseNodeIdUnknown: //case StatusCode.TcpRouterResponseNodeNotReady: // this.DebugReturn(DebugLevel.ERROR, «Unexpected router response: » + statusCode); // break; default: // this.mListener.serverErrorReturn(statusCode.value()); Debug.LogError(«Received unknown status code: « + statusCode); break; } this.externalListener.OnStatusChanged(statusCode); } public void OnEvent(EventData photonEvent) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(string.Format(«OnEvent: {0}«, photonEvent.ToString())); int actorNr = 1; PhotonPlayer originatingPlayer = null; if (photonEvent.Parameters.ContainsKey(ParameterCode.ActorNr)) { actorNr = (int)photonEvent[ParameterCode.ActorNr]; if (this.mActors.ContainsKey(actorNr)) { originatingPlayer = (PhotonPlayer)this.mActors[actorNr]; } //else //{ // // the actor sending this event is not in actorlist. this is usually no problem // if (photonEvent.Code != (byte)LiteOpCode.Join) // { // Debug.LogWarning(«Received event, but we do not have this actor: » + actorNr); // } //} } switch (photonEvent.Code) { case PunEvent.OwnershipRequest: { int[] requestValues = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent]; int requestedViewId = requestValues[0]; int currentOwner = requestValues[1]; Debug.Log(«Ev OwnershipRequest: « + photonEvent.Parameters.ToStringFull() + « ViewID: « + requestedViewId + « from: « + currentOwner + « Time: « + Environment.TickCount%1000); PhotonView requestedView = PhotonView.Find(requestedViewId); if (requestedView == null) { Debug.LogWarning(«Can’t find PhotonView of incoming OwnershipRequest. ViewId not found: « + requestedViewId); break; } Debug.Log(«Ev OwnershipRequest PhotonView.ownershipTransfer: « + requestedView.ownershipTransfer + « .ownerId: « + requestedView.ownerId + « isOwnerActive: « + requestedView.isOwnerActive + «. This client’s player: « + PhotonNetwork.player.ToStringFull()); switch (requestedView.ownershipTransfer) { case OwnershipOption.Fixed: Debug.LogWarning(«Ownership mode == fixed. Ignoring request.«); break; case OwnershipOption.Takeover: if (currentOwner == requestedView.ownerId) { // a takeover is successful automatically, if taken from current owner requestedView.ownerId = actorNr; } break; case OwnershipOption.Request: if (currentOwner == PhotonNetwork.player.ID || PhotonNetwork.player.isMasterClient) { if ((requestedView.ownerId == PhotonNetwork.player.ID) || (PhotonNetwork.player.isMasterClient && !requestedView.isOwnerActive)) { SendMonoMessage(PhotonNetworkingMessage.OnOwnershipRequest, new object[] {requestedView, originatingPlayer}); } } break; default: break; } } break; case PunEvent.OwnershipTransfer: { int[] transferViewToUserID = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent]; Debug.Log(«Ev OwnershipTransfer. ViewID « + transferViewToUserID[0] + « to: « + transferViewToUserID[1] + « Time: « + Environment.TickCount%1000); int requestedViewId = transferViewToUserID[0]; int newOwnerId = transferViewToUserID[1]; PhotonView pv = PhotonView.Find(requestedViewId); pv.ownerId = newOwnerId; break; } case EventCode.GameList: { this.mGameList = new Dictionary<string, RoomInfo>(); Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList]; foreach (DictionaryEntry game in games) { string gameName = (string)game.Key; this.mGameList[gameName] = new RoomInfo(gameName, (Hashtable)game.Value); } mGameListCopy = new RoomInfo[mGameList.Count]; mGameList.Values.CopyTo(mGameListCopy, 0); SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); break; } case EventCode.GameListUpdate: { Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList]; foreach (DictionaryEntry room in games) { string gameName = (string)room.Key; RoomInfo game = new RoomInfo(gameName, (Hashtable)room.Value); if (game.removedFromList) { this.mGameList.Remove(gameName); } else { this.mGameList[gameName] = game; } } this.mGameListCopy = new RoomInfo[this.mGameList.Count]; this.mGameList.Values.CopyTo(this.mGameListCopy, 0); SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate); break; } case EventCode.QueueState: // not used anymore break; case EventCode.AppStats: // Debug.LogInfo(«Received stats!»); this.mPlayersInRoomsCount = (int)photonEvent[ParameterCode.PeerCount]; this.mPlayersOnMasterCount = (int)photonEvent[ParameterCode.MasterPeerCount]; this.mGameCount = (int)photonEvent[ParameterCode.GameCount]; break; case EventCode.Join: // actorNr is fetched out of event above Hashtable actorProperties = (Hashtable)photonEvent[ParameterCode.PlayerProperties]; if (originatingPlayer == null) { bool isLocal = this.mLocalActor.ID == actorNr; this.AddNewPlayer(actorNr, new PhotonPlayer(isLocal, actorNr, actorProperties)); this.ResetPhotonViewsOnSerialize(); // This sets the correct OnSerializeState for Reliable OnSerialize } if (actorNr == this.mLocalActor.ID) { // in this player’s ‘own’ join event, we get a complete list of players in the room, so check if we know all players int[] actorsInRoom = (int[])photonEvent[ParameterCode.ActorList]; foreach (int actorNrToCheck in actorsInRoom) { if (this.mLocalActor.ID != actorNrToCheck && !this.mActors.ContainsKey(actorNrToCheck)) { this.AddNewPlayer(actorNrToCheck, new PhotonPlayer(false, actorNrToCheck, string.Empty)); } } // joinWithCreateOnDemand can turn an OpJoin into creating the room. Then actorNumber is 1 and callback: OnCreatedRoom() if (this.mLastJoinType == JoinType.JoinOrCreateOnDemand && this.mLocalActor.ID == 1) { SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom); } SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); //Always send OnJoinedRoom } else { SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerConnected, this.mActors[actorNr]); } break; case EventCode.Leave: this.HandleEventLeave(actorNr); break; case EventCode.PropertiesChanged: int targetActorNr = (int)photonEvent[ParameterCode.TargetActorNr]; Hashtable gameProperties = null; Hashtable actorProps = null; if (targetActorNr == 0) { gameProperties = (Hashtable)photonEvent[ParameterCode.Properties]; } else { actorProps = (Hashtable)photonEvent[ParameterCode.Properties]; } this.ReadoutProperties(gameProperties, actorProps, targetActorNr); break; case PunEvent.RPC: //ts: each event now contains a single RPC. execute this // Debug.Log(«Ev RPC from: » + originatingPlayer); this.ExecuteRPC(photonEvent[ParameterCode.Data] as Hashtable, originatingPlayer); break; case PunEvent.SendSerialize: case PunEvent.SendSerializeReliable: Hashtable serializeData = (Hashtable)photonEvent[ParameterCode.Data]; //Debug.Log(serializeData.ToStringFull()); int remoteUpdateServerTimestamp = (int)serializeData[(byte)0]; short remoteLevelPrefix = 1; short initialDataIndex = 1; if (serializeData.ContainsKey((byte)1)) { remoteLevelPrefix = (short)serializeData[(byte)1]; initialDataIndex = 2; } for (short s = initialDataIndex; s < serializeData.Count; s++) { this.OnSerializeRead(serializeData[s] as Hashtable, originatingPlayer, remoteUpdateServerTimestamp, remoteLevelPrefix); } break; case PunEvent.Instantiation: this.DoInstantiate((Hashtable)photonEvent[ParameterCode.Data], originatingPlayer, null); break; case PunEvent.CloseConnection: // MasterClient «requests» a disconnection from us if (originatingPlayer == null || !originatingPlayer.isMasterClient) { Debug.LogError(«Error: Someone else(« + originatingPlayer + «) then the masterserver requests a disconnect!«); } else { PhotonNetwork.LeaveRoom(); } break; case PunEvent.DestroyPlayer: Hashtable evData = (Hashtable)photonEvent[ParameterCode.Data]; int targetPlayerId = (int)evData[(byte)0]; if (targetPlayerId >= 0) { this.DestroyPlayerObjects(targetPlayerId, true); } else { if (this.DebugOut >= DebugLevel.INFO) Debug.Log(«Ev DestroyAll! By PlayerId: « + actorNr); this.DestroyAll(true); } break; case PunEvent.Destroy: evData = (Hashtable)photonEvent[ParameterCode.Data]; int instantiationId = (int)evData[(byte)0]; // Debug.Log(«Ev Destroy for viewId: » + instantiationId + » sent by owner: » + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == actorNr) + » this client is owner: » + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == this.mLocalActor.ID)); PhotonView pvToDestroy = null; if (this.photonViewList.TryGetValue(instantiationId, out pvToDestroy)) { this.RemoveInstantiatedGO(pvToDestroy.gameObject, true); } else { if (this.DebugOut >= DebugLevel.ERROR) Debug.LogError(«Ev Destroy Failed. Could not find PhotonView with instantiationId « + instantiationId + «. Sent by actorNr: « + actorNr); } break; case PunEvent.AssignMaster: evData = (Hashtable)photonEvent[ParameterCode.Data]; int newMaster = (int)evData[(byte)1]; this.SetMasterClient(newMaster, false); break; default: if (photonEvent.Code < 200 && PhotonNetwork.OnEventCall != null) { object content = photonEvent[ParameterCode.Data]; PhotonNetwork.OnEventCall(photonEvent.Code, content, actorNr); } else { // actorNr might be null. it is fetched out of event on top of method // Hashtable eventContent = (Hashtable) photonEvent[ParameterCode.Data]; // this.mListener.customEventAction(actorNr, eventCode, eventContent); Debug.LogError(«Error. Unhandled event: « + photonEvent); } break; } this.externalListener.OnEvent(photonEvent); } private void SendVacantViewIds() { Debug.Log(«SendVacantViewIds()«); List<int> vacantViews = new List<int>(); foreach (PhotonView view in this.photonViewList.Values) { if (!view.isOwnerActive) { vacantViews.Add(view.viewID); } } Debug.Log(«Sending vacant view IDs. Length: « + vacantViews.Count); //this.OpRaiseEvent(PunEvent.VacantViewIds, true, vacantViews.ToArray()); this.OpRaiseEvent(PunEvent.VacantViewIds, vacantViews.ToArray(), true, null); } #endregion public static void SendMonoMessage(PhotonNetworkingMessage methodString, params object[] parameters) { HashSet<GameObject> objectsToCall; if (PhotonNetwork.SendMonoMessageTargets != null) { objectsToCall = PhotonNetwork.SendMonoMessageTargets; } else { objectsToCall = PhotonNetwork.FindGameObjectsWithComponent(PhotonNetwork.SendMonoMessageTargetType); } string methodName = methodString.ToString(); object callParameter = (parameters != null && parameters.Length == 1) ? parameters[0] : parameters; foreach (GameObject gameObject in objectsToCall) { gameObject.SendMessage(methodName, callParameter, SendMessageOptions.DontRequireReceiver); } } // PHOTONVIEW/RPC related /// <summary> /// Executes a received RPC event /// </summary> public void ExecuteRPC(Hashtable rpcData, PhotonPlayer sender) { if (rpcData == null || !rpcData.ContainsKey((byte)0)) { Debug.LogError(«Malformed RPC; this should never occur. Content: « + SupportClass.DictionaryToString(rpcData)); return; } // ts: updated with «flat» event data int netViewID = (int)rpcData[(byte)0]; // LIMITS PHOTONVIEWS&PLAYERS int otherSidePrefix = 0; // by default, the prefix is 0 (and this is not being sent) if (rpcData.ContainsKey((byte)1)) { otherSidePrefix = (short)rpcData[(byte)1]; } string inMethodName; if (rpcData.ContainsKey((byte)5)) { int rpcIndex = (byte)rpcData[(byte)5]; // LIMITS RPC COUNT if (rpcIndex > PhotonNetwork.PhotonServerSettings.RpcList.Count 1) { Debug.LogError(«Could not find RPC with index: « + rpcIndex + «. Going to ignore! Check PhotonServerSettings.RpcList«); return; } else { inMethodName = PhotonNetwork.PhotonServerSettings.RpcList[rpcIndex]; } } else { inMethodName = (string)rpcData[(byte)3]; } object[] inMethodParameters = null; if (rpcData.ContainsKey((byte)4)) { inMethodParameters = (object[])rpcData[(byte)4]; } if (inMethodParameters == null) { inMethodParameters = new object[0]; } PhotonView photonNetview = this.GetPhotonView(netViewID); if (photonNetview == null) { int viewOwnerId = netViewID/PhotonNetwork.MAX_VIEW_IDS; bool owningPv = (viewOwnerId == this.mLocalActor.ID); bool ownerSent = (viewOwnerId == sender.ID); if (owningPv) { Debug.LogWarning(«Received RPC «« + inMethodName + «« for viewID « + netViewID + « but this PhotonView does not exist! View was/is ours.« + (ownerSent ? « Owner called.« : « Remote called.«) + « By: « + sender.ID); } else { Debug.LogWarning(«Received RPC «« + inMethodName + «« for viewID « + netViewID + « but this PhotonView does not exist! Was remote PV.« + (ownerSent ? « Owner called.« : « Remote called.«) + « By: « + sender.ID + « Maybe GO was destroyed but RPC not cleaned up.«); } return; } if (photonNetview.prefix != otherSidePrefix) { Debug.LogError( «Received RPC «« + inMethodName + «« on viewID « + netViewID + « with a prefix of « + otherSidePrefix + «, our prefix is « + photonNetview.prefix + «. The RPC has been ignored.«); return; } // Get method name if (inMethodName == string.Empty) { Debug.LogError(«Malformed RPC; this should never occur. Content: « + SupportClass.DictionaryToString(rpcData)); return; } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Received RPC: « + inMethodName); // SetReceiving filtering if (photonNetview.group != 0 && !allowedReceivingGroups.Contains(photonNetview.group)) { return; // Ignore group } Type[] argTypes = new Type[0]; if (inMethodParameters.Length > 0) { argTypes = new Type[inMethodParameters.Length]; int i = 0; for (int index = 0; index < inMethodParameters.Length; index++) { object objX = inMethodParameters[index]; if (objX == null) { argTypes[i] = null; } else { argTypes[i] = objX.GetType(); } i++; } } int receivers = 0; int foundMethods = 0; MonoBehaviour[] mbComponents = photonNetview.GetComponents<MonoBehaviour>(); // NOTE: we could possibly also cache MonoBehaviours per view?! for (int componentsIndex = 0; componentsIndex < mbComponents.Length; componentsIndex++) { MonoBehaviour monob = mbComponents[componentsIndex]; if (monob == null) { Debug.LogError(«ERROR You have missing MonoBehaviours on your gameobjects!«); continue; } Type type = monob.GetType(); // Get [RPC] methods from cache List<MethodInfo> cachedRPCMethods = null; if (this.monoRPCMethodsCache.ContainsKey(type)) { cachedRPCMethods = this.monoRPCMethodsCache[type]; } if (cachedRPCMethods == null) { List<MethodInfo> entries = SupportClass.GetMethods(type, typeof(RPC)); this.monoRPCMethodsCache[type] = entries; cachedRPCMethods = entries; } if (cachedRPCMethods == null) { continue; } // Check cache for valid methodname+arguments for (int index = 0; index < cachedRPCMethods.Count; index++) { MethodInfo mInfo = cachedRPCMethods[index]; if (mInfo.Name == inMethodName) { foundMethods++; ParameterInfo[] pArray = mInfo.GetParameters(); if (pArray.Length == argTypes.Length) { // Normal, PhotonNetworkMessage left out if (this.CheckTypeMatch(pArray, argTypes)) { receivers++; object result = mInfo.Invoke((object)monob, inMethodParameters); if (mInfo.ReturnType == typeof(IEnumerator)) { monob.StartCoroutine((IEnumerator)result); } } } else if ((pArray.Length 1) == argTypes.Length) { // Check for PhotonNetworkMessage being the last if (this.CheckTypeMatch(pArray, argTypes)) { if (pArray[pArray.Length 1].ParameterType == typeof(PhotonMessageInfo)) { receivers++; int sendTime = (int)rpcData[(byte)2]; object[] deParamsWithInfo = new object[inMethodParameters.Length + 1]; inMethodParameters.CopyTo(deParamsWithInfo, 0); deParamsWithInfo[deParamsWithInfo.Length 1] = new PhotonMessageInfo(sender, sendTime, photonNetview); object result = mInfo.Invoke((object)monob, deParamsWithInfo); if (mInfo.ReturnType == typeof(IEnumerator)) { monob.StartCoroutine((IEnumerator)result); } } } } else if (pArray.Length == 1 && pArray[0].ParameterType.IsArray) { receivers++; object result = mInfo.Invoke((object)monob, new object[] { inMethodParameters }); if (mInfo.ReturnType == typeof(IEnumerator)) { monob.StartCoroutine((IEnumerator)result); } } } } } // Error handling if (receivers != 1) { string argsString = string.Empty; for (int index = 0; index < argTypes.Length; index++) { Type ty = argTypes[index]; if (argsString != string.Empty) { argsString += «, «; } if (ty == null) { argsString += «null«; } else { argsString += ty.Name; } } if (receivers == 0) { if (foundMethods == 0) { Debug.LogError(«PhotonView with ID « + netViewID + « has no method «« + inMethodName + «« marked with the [RPC](C#) or @RPC(JS) property! Args: « + argsString); } else { Debug.LogError(«PhotonView with ID « + netViewID + « has no method «« + inMethodName + «« that takes « + argTypes.Length + « argument(s): « + argsString); } } else { Debug.LogError(«PhotonView with ID « + netViewID + « has « + receivers + « methods «« + inMethodName + «« that takes « + argTypes.Length + « argument(s): « + argsString + «. Should be just one?«); } } } /// <summary> /// Check if all types match with parameters. We can have more paramters then types (allow last RPC type to be different). /// </summary> /// <param name=«methodParameters«></param> /// <param name=«callParameterTypes«></param> /// <returns>If the types-array has matching parameters (of method) in the parameters array (which may be longer).</returns> private bool CheckTypeMatch(ParameterInfo[] methodParameters, Type[] callParameterTypes) { if (methodParameters.Length < callParameterTypes.Length) { return false; } for (int index = 0; index < callParameterTypes.Length; index++) { Type type = methodParameters[index].ParameterType; //todo: check metro type usage if (callParameterTypes[index] != null && !type.Equals(callParameterTypes[index])) { return false; } } return true; } internal Hashtable SendInstantiate(string prefabName, Vector3 position, Quaternion rotation, int group, int[] viewIDs, object[] data, bool isGlobalObject) { // first viewID is now also the gameobject’s instantiateId int instantiateId = viewIDs[0]; // LIMITS PHOTONVIEWS&PLAYERS //TODO: reduce hashtable key usage by using a parameter array for the various values Hashtable instantiateEvent = new Hashtable(); // This players info is sent via ActorID instantiateEvent[(byte)0] = prefabName; if (position != Vector3.zero) { instantiateEvent[(byte)1] = position; } if (rotation != Quaternion.identity) { instantiateEvent[(byte)2] = rotation; } if (group != 0) { instantiateEvent[(byte)3] = group; } // send the list of viewIDs only if there are more than one. else the instantiateId is the viewID if (viewIDs.Length > 1) { instantiateEvent[(byte)4] = viewIDs; // LIMITS PHOTONVIEWS&PLAYERS } if (data != null) { instantiateEvent[(byte)5] = data; } if (this.currentLevelPrefix > 0) { instantiateEvent[(byte)8] = this.currentLevelPrefix; // photonview’s / object’s level prefix } instantiateEvent[(byte)6] = this.ServerTimeInMilliSeconds; instantiateEvent[(byte)7] = instantiateId; RaiseEventOptions options = new RaiseEventOptions(); options.CachingOption = (isGlobalObject) ? EventCaching.AddToRoomCacheGlobal : EventCaching.AddToRoomCache; this.OpRaiseEvent(PunEvent.Instantiation, instantiateEvent, true, options); return instantiateEvent; } internal GameObject DoInstantiate(Hashtable evData, PhotonPlayer photonPlayer, GameObject resourceGameObject) { // some values always present: string prefabName = (string)evData[(byte)0]; int serverTime = (int)evData[(byte)6]; int instantiationId = (int)evData[(byte)7]; Vector3 position; if (evData.ContainsKey((byte)1)) { position = (Vector3)evData[(byte)1]; } else { position = Vector3.zero; } Quaternion rotation = Quaternion.identity; if (evData.ContainsKey((byte)2)) { rotation = (Quaternion)evData[(byte)2]; } int group = 0; if (evData.ContainsKey((byte)3)) { group = (int)evData[(byte)3]; } short objLevelPrefix = 0; if (evData.ContainsKey((byte)8)) { objLevelPrefix = (short)evData[(byte)8]; } int[] viewsIDs; if (evData.ContainsKey((byte)4)) { viewsIDs = (int[])evData[(byte)4]; } else { viewsIDs = new int[1] { instantiationId }; } object[] incomingInstantiationData; if (evData.ContainsKey((byte)5)) { incomingInstantiationData = (object[])evData[(byte)5]; } else { incomingInstantiationData = null; } // SetReceiving filtering if (group != 0 && !this.allowedReceivingGroups.Contains(group)) { return null; // Ignore group } // load prefab, if it wasn’t loaded before (calling methods might do this) if (resourceGameObject == null) { if (!NetworkingPeer.UsePrefabCache || !NetworkingPeer.PrefabCache.TryGetValue(prefabName, out resourceGameObject)) { resourceGameObject = (GameObject)Resources.Load(prefabName, typeof(GameObject)); if (NetworkingPeer.UsePrefabCache) { NetworkingPeer.PrefabCache.Add(prefabName, resourceGameObject); } } if (resourceGameObject == null) { Debug.LogError(«PhotonNetwork error: Could not Instantiate the prefab [« + prefabName + «]. Please verify you have this gameobject in a Resources folder.«); return null; } } // now modify the loaded «blueprint» object before it becomes a part of the scene (by instantiating it) PhotonView[] resourcePVs = resourceGameObject.GetPhotonViewsInChildren(); if (resourcePVs.Length != viewsIDs.Length) { throw new Exception(«Error in Instantiation! The resource’s PhotonView count is not the same as in incoming data.«); } for (int i = 0; i < viewsIDs.Length; i++) { // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it’s set below // so we only set the viewID and instantiationId now. the instantiationData can be fetched resourcePVs[i].viewID = viewsIDs[i]; resourcePVs[i].prefix = objLevelPrefix; resourcePVs[i].instantiationId = instantiationId; resourcePVs[i].isRuntimeInstantiated = true; } this.StoreInstantiationData(instantiationId, incomingInstantiationData); // load the resource and set it’s values before instantiating it: GameObject go = (GameObject)GameObject.Instantiate(resourceGameObject, position, rotation); for (int i = 0; i < viewsIDs.Length; i++) { // NOTE instantiating the loaded resource will keep the viewID but would not copy instantiation data, so it’s set below // so we only set the viewID and instantiationId now. the instantiationData can be fetched resourcePVs[i].viewID = 0; resourcePVs[i].prefix = 1; resourcePVs[i].prefixBackup = 1; resourcePVs[i].instantiationId = 1; resourcePVs[i].isRuntimeInstantiated = false; } this.RemoveInstantiationData(instantiationId); // Send OnPhotonInstantiate callback to newly created GO. // GO will be enabled when instantiated from Prefab and it does not matter if the script is enabled or disabled. go.SendMessage(PhotonNetworkingMessage.OnPhotonInstantiate.ToString(), new PhotonMessageInfo(photonPlayer, serverTime, null), SendMessageOptions.DontRequireReceiver); return go; } private Dictionary<int, object[]> tempInstantiationData = new Dictionary<int, object[]>(); private void StoreInstantiationData(int instantiationId, object[] instantiationData) { // Debug.Log(«StoreInstantiationData() instantiationId: » + instantiationId + » tempInstantiationData.Count: » + tempInstantiationData.Count); tempInstantiationData[instantiationId] = instantiationData; } public object[] FetchInstantiationData(int instantiationId) { object[] data = null; if (instantiationId == 0) { return null; } tempInstantiationData.TryGetValue(instantiationId, out data); // Debug.Log(«FetchInstantiationData() instantiationId: » + instantiationId + » tempInstantiationData.Count: » + tempInstantiationData.Count); return data; } private void RemoveInstantiationData(int instantiationId) { tempInstantiationData.Remove(instantiationId); } /// <summary> /// Destroys all Instantiates and RPCs locally and (if not localOnly) sends EvDestroy(player) and clears related events in the server buffer. /// </summary> public void DestroyPlayerObjects(int playerId, bool localOnly) { if (playerId <= 0) { Debug.LogError(«Failed to Destroy objects of playerId: « + playerId); return; } if (!localOnly) { // clean server’s Instantiate and RPC buffers this.OpRemoveFromServerInstantiationsOfPlayer(playerId); this.OpCleanRpcBuffer(playerId); // send Destroy(player) to anyone else this.SendDestroyOfPlayer(playerId); } // locally cleaning up that player’s objects HashSet<GameObject> playersGameObjects = new HashSet<GameObject>(); foreach (PhotonView view in this.photonViewList.Values) { if (view.CreatorActorNr == playerId) { playersGameObjects.Add(view.gameObject); } } // any non-local work is already done, so with the list of that player’s objects, we can clean up (locally only) foreach (GameObject gameObject in playersGameObjects) { this.RemoveInstantiatedGO(gameObject, true); } // with ownership transfer, some objects might lose their owner. // in that case, the creator becomes the owner again. every client can apply this. done below. foreach (PhotonView view in this.photonViewList.Values) { if (view.ownerId == playerId) { view.ownerId = view.CreatorActorNr; //Debug.Log(«Creator is: » + view.ownerId); } } } public void DestroyAll(bool localOnly) { if (!localOnly) { this.OpRemoveCompleteCache(); this.SendDestroyOfAll(); } this.LocalCleanupAnythingInstantiated(true); } /// <summary>Removes GameObject and the PhotonViews on it from local lists and optionally updates remotes. GameObject gets destroyed at end.</summary> /// <remarks> /// This method might fail and quit early due to several tests. /// </remarks> /// <param name=«go«>GameObject to cleanup.</param> /// <param name=«localOnly«>For localOnly, tests of control are skipped and the server is not updated.</param> protected internal void RemoveInstantiatedGO(GameObject go, bool localOnly) { if (go == null) { Debug.LogError(«Failed to ‘network-remove’ GameObject because it’s null.«); return; } // Don’t remove the GO if it doesn’t have any PhotonView PhotonView[] views = go.GetComponentsInChildren<PhotonView>(true); if (views == null || views.Length <= 0) { Debug.LogError(«Failed to ‘network-remove’ GameObject because has no PhotonView components: « + go); return; } PhotonView viewZero = views[0]; int creatorId = viewZero.CreatorActorNr; // creatorId of obj is needed to delete EvInstantiate (only if it’s from that user) int instantiationId = viewZero.instantiationId; // actual, live InstantiationIds start with 1 and go up // Don’t remove GOs that are owned by others (unless this is the master and the remote player left) if (!localOnly) { if (!viewZero.isMine) { Debug.LogError(«Failed to ‘network-remove’ GameObject. Client is neither owner nor masterClient taking over for owner who left: « + viewZero); return; } // Don’t remove the Instantiation from the server, if it doesn’t have a proper ID if (instantiationId < 1) { Debug.LogError(«Failed to ‘network-remove’ GameObject because it is missing a valid InstantiationId on view: « + viewZero + «. Not Destroying GameObject or PhotonViews!«); return; } } // cleanup instantiation (event and local list) if (!localOnly) { this.ServerCleanInstantiateAndDestroy(instantiationId, creatorId, viewZero.isRuntimeInstantiated); // server cleaning } // cleanup PhotonViews and their RPCs events (if not localOnly) for (int j = views.Length 1; j >= 0; j) { PhotonView view = views[j]; if (view == null) { continue; } // we only destroy/clean PhotonViews that were created by PhotonNetwork.Instantiate (and those have an instantiationId!) if (view.instantiationId >= 1) { this.LocalCleanPhotonView(view); } if (!localOnly) { this.OpCleanRpcBuffer(view); } } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Network destroy Instantiated GO: « + go.name); GameObject.Destroy(go); } /// <summary> /// This returns -1 if the GO could not be found in list of instantiatedObjects. /// </summary> public int GetInstantiatedObjectsId(GameObject go) { int id = 1; if (go == null) { Debug.LogError(«GetInstantiatedObjectsId() for GO == null.«); return id; } PhotonView[] pvs = go.GetPhotonViewsInChildren(); if (pvs != null && pvs.Length > 0 && pvs[0] != null) { return pvs[0].instantiationId; } if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) UnityEngine.Debug.Log(«GetInstantiatedObjectsId failed for GO: « + go); return id; } /// <summary> /// Removes an instantiation event from the server’s cache. Needs id and actorNr of player who instantiated. /// </summary> private void ServerCleanInstantiateAndDestroy(int instantiateId, int creatorId, bool isRuntimeInstantiated) { Hashtable removeFilter = new Hashtable(); removeFilter[(byte)7] = instantiateId; RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { creatorId } }; this.OpRaiseEvent(PunEvent.Instantiation, removeFilter, true, options); //this.OpRaiseEvent(PunEvent.Instantiation, removeFilter, true, 0, new int[] { actorNr }, EventCaching.RemoveFromRoomCache); Hashtable evData = new Hashtable(); evData[(byte)0] = instantiateId; options = null; if (!isRuntimeInstantiated) { // if the view got loaded with the scene, the EvDestroy must be cached (there is no Instantiate-msg which we can remove) // reason: joining players will load the obj and have to destroy it (too) options = new RaiseEventOptions(); options.CachingOption = EventCaching.AddToRoomCacheGlobal; Debug.Log(«Destroying GO as global. ID: « + instantiateId); } this.OpRaiseEvent(PunEvent.Destroy, evData, true, options); } private void SendDestroyOfPlayer(int actorNr) { Hashtable evData = new Hashtable(); evData[(byte)0] = actorNr; this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, null); //this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, 0, EventCaching.DoNotCache, ReceiverGroup.Others); } private void SendDestroyOfAll() { Hashtable evData = new Hashtable(); evData[(byte)0] = 1; this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, null); //this.OpRaiseEvent(PunEvent.DestroyPlayer, evData, true, 0, EventCaching.DoNotCache, ReceiverGroup.Others); } private void OpRemoveFromServerInstantiationsOfPlayer(int actorNr) { // removes all «Instantiation» events of player actorNr. this is not an event for anyone else RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNr } }; this.OpRaiseEvent(PunEvent.Instantiation, null, true, options); //this.OpRaiseEvent(PunEvent.Instantiation, null, true, 0, new int[] { actorNr }, EventCaching.RemoveFromRoomCache); } internal protected void RequestOwnership(int viewID, int fromOwner) { Debug.Log(«RequestOwnership(): « + viewID + « from: « + fromOwner + « Time: « + Environment.TickCount % 1000); //PhotonNetwork.networkingPeer.OpRaiseEvent(PunEvent.OwnershipRequest, true, new int[] { viewID, fromOwner }, 0, EventCaching.DoNotCache, null, ReceiverGroup.All, 0); this.OpRaiseEvent(PunEvent.OwnershipRequest, new int[] {viewID, fromOwner}, true, new RaiseEventOptions() { Receivers = ReceiverGroup.All }); // All sends to all via server (including self) } internal protected void TransferOwnership(int viewID, int playerID) { Debug.Log(«TransferOwnership() view « + viewID + « to: « + playerID + « Time: « + Environment.TickCount % 1000); //PhotonNetwork.networkingPeer.OpRaiseEvent(PunEvent.OwnershipTransfer, true, new int[] {viewID, playerID}, 0, EventCaching.DoNotCache, null, ReceiverGroup.All, 0); this.OpRaiseEvent(PunEvent.OwnershipTransfer, new int[] { viewID, playerID }, true, new RaiseEventOptions() { Receivers = ReceiverGroup.All }); // All sends to all via server (including self) } public void LocalCleanPhotonView(PhotonView view) { view.destroyedByPhotonNetworkOrQuit = true; this.photonViewList.Remove(view.viewID); } public PhotonView GetPhotonView(int viewID) { PhotonView result = null; this.photonViewList.TryGetValue(viewID, out result); if (result == null) { PhotonView[] views = GameObject.FindObjectsOfType(typeof(PhotonView)) as PhotonView[]; foreach (PhotonView view in views) { if (view.viewID == viewID) { if (view.didAwake) { Debug.LogWarning(«Had to lookup view that wasn’t in photonViewList: « + view); } return view; } } } return result; } public void RegisterPhotonView(PhotonView netView) { if (!Application.isPlaying) { this.photonViewList = new Dictionary<int, PhotonView>(); return; } if (netView.viewID == 0) { // don’t register views with ID 0 (not initialized). they register when a ID is assigned later on Debug.Log(«PhotonView register is ignored, because viewID is 0. No id assigned yet to: « + netView); return; } if (this.photonViewList.ContainsKey(netView.viewID)) { // if some other view is in the list already, we got a problem. it might be undestructible. print out error if (netView != photonViewList[netView.viewID]) { Debug.LogError(string.Format(«PhotonView ID duplicate found: {0}. New: {1} old: {2}. Maybe one wasn’t destroyed on scene load?! Check for ‘DontDestroyOnLoad’. Destroying old entry, adding new.«, netView.viewID, netView, photonViewList[netView.viewID])); } //this.photonViewList.Remove(netView.viewID); // TODO check if we chould Destroy the GO of this view?! this.RemoveInstantiatedGO(photonViewList[netView.viewID].gameObject, true); } // Debug.Log(«adding view to known list: » + netView); this.photonViewList.Add(netView.viewID, netView); //Debug.LogError(«view being added. » + netView); // Exit Games internal log if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Registered PhotonView: « + netView.viewID); } ///// <summary> ///// Will remove the view from list of views (by its ID). ///// </summary> //public void RemovePhotonView(PhotonView netView) //{ // if (!Application.isPlaying) // { // this.photonViewList = new Dictionary<int, PhotonView>(); // return; // } // //PhotonView removedView = null; // //this.photonViewList.TryGetValue(netView.viewID, out removedView); // //if (removedView != netView) // //{ // // Debug.LogError(«Detected two differing PhotonViews with same viewID: » + netView.viewID); // //} // this.photonViewList.Remove(netView.viewID); // //if (this.DebugOut >= DebugLevel.ALL) // //{ // // this.DebugReturn(DebugLevel.ALL, «Removed PhotonView: » + netView.viewID); // //} //} /// <summary> /// Removes the RPCs of someone else (to be used as master). /// This won’t clean any local caches. It just tells the server to forget a player’s RPCs and instantiates. /// </summary> /// <param name=«actorNumber«></param> public void OpCleanRpcBuffer(int actorNumber) { RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNumber } }; this.OpRaiseEvent(PunEvent.RPC, null, true, options); //this.OpRaiseEvent(PunEvent.RPC, null, true, 0, new int[] { actorNumber }, EventCaching.RemoveFromRoomCache); } /// <summary> /// Instead removing RPCs or Instantiates, this removed everything cached by the actor. /// </summary> /// <param name=«actorNumber«></param> public void OpRemoveCompleteCacheOfPlayer(int actorNumber) { RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, TargetActors = new int[] { actorNumber } }; this.OpRaiseEvent(0, null, true, options); //this.OpRaiseEvent(0, null, true, 0, new int[] { actorNumber }, EventCaching.RemoveFromRoomCache); } public void OpRemoveCompleteCache() { RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache, Receivers = ReceiverGroup.MasterClient }; this.OpRaiseEvent(0, null, true, options); //this.OpRaiseEvent(0, null, true, 0, EventCaching.RemoveFromRoomCache, ReceiverGroup.MasterClient); // TODO: check who gets this event? } /// This clears the cache of any player/actor who’s no longer in the room (making it a simple clean-up option for a new master) private void RemoveCacheOfLeftPlayers() { Dictionary<byte, object> opParameters = new Dictionary<byte, object>(); opParameters[ParameterCode.Code] = (byte)0; // any event opParameters[ParameterCode.Cache] = (byte)EventCaching.RemoveFromRoomCacheForActorsLeft; // option to clear the room cache of all events of players who left this.OpCustom((byte)OperationCode.RaiseEvent, opParameters, true, 0); } // Remove RPCs of view (if they are local player’s RPCs) public void CleanRpcBufferIfMine(PhotonView view) { if (view.ownerId != this.mLocalActor.ID && !mLocalActor.isMasterClient) { Debug.LogError(«Cannot remove cached RPCs on a PhotonView thats not ours! « + view.owner + « scene: « + view.isSceneView); return; } this.OpCleanRpcBuffer(view); } /// <summary>Cleans server RPCs for PhotonView (without any further checks).</summary> public void OpCleanRpcBuffer(PhotonView view) { Hashtable rpcFilterByViewId = new Hashtable(); rpcFilterByViewId[(byte)0] = view.viewID; RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.RemoveFromRoomCache }; this.OpRaiseEvent(PunEvent.RPC, rpcFilterByViewId, true, options); //this.OpRaiseEvent(PunEvent.RPC, rpcFilterByViewId, true, 0, EventCaching.RemoveFromRoomCache, ReceiverGroup.Others); } public void RemoveRPCsInGroup(int group) { foreach (KeyValuePair<int, PhotonView> kvp in this.photonViewList) { PhotonView view = kvp.Value; if (view.group == group) { this.CleanRpcBufferIfMine(view); } } } public void SetLevelPrefix(short prefix) { this.currentLevelPrefix = prefix; // TODO: should we really change the prefix for existing PVs?! better keep it! //foreach (PhotonView view in this.photonViewList.Values) //{ // view.prefix = prefix; //} } internal void RPC(PhotonView view, string methodName, PhotonPlayer player, bool encrypt, params object[] parameters) { if (this.blockSendingGroups.Contains(view.group)) { return; // Block sending on this group } if (view.viewID < 1) //TODO: check why 0 should be illegal { Debug.LogError(«Illegal view ID:« + view.viewID + « method: « + methodName + « GO:« + view.gameObject.name); } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) { Debug.Log(«Sending RPC «« + methodName + «« to player[« + player + «]«); } //ts: changed RPCs to a one-level hashtable as described in internal.txt Hashtable rpcEvent = new Hashtable(); rpcEvent[(byte)0] = (int)view.viewID; // LIMITS PHOTONVIEWS&PLAYERS if (view.prefix > 0) { rpcEvent[(byte)1] = (short)view.prefix; } rpcEvent[(byte)2] = this.ServerTimeInMilliSeconds; // send name or shortcut (if available) int shortcut = 0; if (rpcShortcuts.TryGetValue(methodName, out shortcut)) { rpcEvent[(byte)5] = (byte)shortcut; // LIMITS RPC COUNT } else { rpcEvent[(byte)3] = methodName; } if (parameters != null && parameters.Length > 0) { rpcEvent[(byte) 4] = (object[]) parameters; } if (this.mLocalActor == player) { this.ExecuteRPC(rpcEvent, player); } else { RaiseEventOptions options = new RaiseEventOptions() { TargetActors = new int[] { player.ID }, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); } } /// RPC Hashtable Structure /// (byte)0 -> (int) ViewId (combined from actorNr and actor-unique-id) /// (byte)1 -> (short) prefix (level) /// (byte)2 -> (int) server timestamp /// (byte)3 -> (string) methodname /// (byte)4 -> (object[]) parameters /// (byte)5 -> (byte) method shortcut (alternative to name) /// /// This is sent as event (code: 200) which will contain a sender (origin of this RPC). internal void RPC(PhotonView view, string methodName, PhotonTargets target, bool encrypt, params object[] parameters) { if (this.blockSendingGroups.Contains(view.group)) { return; // Block sending on this group } if (view.viewID < 1) { Debug.LogError(«Illegal view ID:« + view.viewID + « method: « + methodName + « GO:« + view.gameObject.name); } if (PhotonNetwork.logLevel >= PhotonLogLevel.Full) Debug.Log(«Sending RPC «« + methodName + «« to « + target); //ts: changed RPCs to a one-level hashtable as described in internal.txt Hashtable rpcEvent = new Hashtable(); rpcEvent[(byte)0] = (int)view.viewID; // LIMITS NETWORKVIEWS&PLAYERS if (view.prefix > 0) { rpcEvent[(byte)1] = (short)view.prefix; } rpcEvent[(byte)2] = this.ServerTimeInMilliSeconds; // send name or shortcut (if available) int shortcut = 0; if (rpcShortcuts.TryGetValue(methodName, out shortcut)) { rpcEvent[(byte)5] = (byte)shortcut; // LIMITS RPC COUNT } else { rpcEvent[(byte)3] = methodName; } if (parameters != null && parameters.Length > 0) { rpcEvent[(byte)4] = (object[])parameters; } // Check scoping if (target == PhotonTargets.All) { RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); // Execute local this.ExecuteRPC(rpcEvent, this.mLocalActor); } else if (target == PhotonTargets.Others) { RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); } else if (target == PhotonTargets.AllBuffered) { RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); // Execute local this.ExecuteRPC(rpcEvent, this.mLocalActor); } else if (target == PhotonTargets.OthersBuffered) { RaiseEventOptions options = new RaiseEventOptions() { CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); } else if (target == PhotonTargets.MasterClient) { if (this.mMasterClient == this.mLocalActor) { this.ExecuteRPC(rpcEvent, this.mLocalActor); } else { RaiseEventOptions options = new RaiseEventOptions() { Receivers = ReceiverGroup.MasterClient, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); } } else if (target == PhotonTargets.AllViaServer) { RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Receivers = ReceiverGroup.All, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); if (PhotonNetwork.offlineMode) { this.ExecuteRPC(rpcEvent, this.mLocalActor); } } else if (target == PhotonTargets.AllBufferedViaServer) { RaiseEventOptions options = new RaiseEventOptions() { InterestGroup = (byte)view.group, Receivers = ReceiverGroup.All, CachingOption = EventCaching.AddToRoomCache, Encrypt = encrypt }; this.OpRaiseEvent(PunEvent.RPC, rpcEvent, true, options); if (PhotonNetwork.offlineMode) { this.ExecuteRPC(rpcEvent, this.mLocalActor); } } else { Debug.LogError(«Unsupported target enum: « + target); } } // SetReceiving public void SetReceivingEnabled(int group, bool enabled) { if (group <= 0) { Debug.LogError(«Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: « + group + «. The group number should be at least 1.«); return; } if (enabled) { if (!this.allowedReceivingGroups.Contains(group)) { this.allowedReceivingGroups.Add(group); byte[] groups = new byte[1] { (byte)group }; this.OpChangeGroups(null, groups); } } else { if (this.allowedReceivingGroups.Contains(group)) { this.allowedReceivingGroups.Remove(group); byte[] groups = new byte[1] { (byte)group }; this.OpChangeGroups(groups, null); } } } public void SetReceivingEnabled(int[] enableGroups, int[] disableGroups) { List<byte> enableList = new List<byte>(); List<byte> disableList = new List<byte>(); if (enableGroups != null) { for (int index = 0; index < enableGroups.Length; index++) { int i = enableGroups[index]; if (i <= 0) { Debug.LogError(«Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: « + i + «. The group number should be at least 1.«); continue; } if (!this.allowedReceivingGroups.Contains(i)) { this.allowedReceivingGroups.Add(i); enableList.Add((byte)i); } } } if (disableGroups != null) { for (int index = 0; index < disableGroups.Length; index++) { int i = disableGroups[index]; if (i <= 0) { Debug.LogError(«Error: PhotonNetwork.SetReceivingEnabled was called with an illegal group number: « + i + «. The group number should be at least 1.«); continue; } if (enableList.Contains((byte)i)) { Debug.LogError(«Error: PhotonNetwork.SetReceivingEnabled disableGroups contains a group that is also in the enableGroups: « + i + «.«); continue; } if (this.allowedReceivingGroups.Contains(i)) { this.allowedReceivingGroups.Remove(i); disableList.Add((byte)i); } } } this.OpChangeGroups(disableList.Count > 0 ? disableList.ToArray() : null, enableList.Count > 0 ? enableList.ToArray() : null); //Passing a 0 sized array != passing null } // SetSending public void SetSendingEnabled(int group, bool enabled) { if (!enabled) { this.blockSendingGroups.Add(group); // can be added to HashSet no matter if already in it } else { this.blockSendingGroups.Remove(group); } } public void SetSendingEnabled(int[] enableGroups, int[] disableGroups) { if(enableGroups!=null){ foreach(int i in enableGroups){ if(this.blockSendingGroups.Contains(i)) this.blockSendingGroups.Remove(i); } } if(disableGroups!=null){ foreach(int i in disableGroups){ if(!this.blockSendingGroups.Contains(i)) this.blockSendingGroups.Add(i); } } } public void NewSceneLoaded() { if (this.loadingLevelAndPausedNetwork) { this.loadingLevelAndPausedNetwork = false; PhotonNetwork.isMessageQueueRunning = true; } // Debug.Log(«OnLevelWasLoaded photonViewList.Count: » + photonViewList.Count); // Exit Games internal log List<int> removeKeys = new List<int>(); foreach (KeyValuePair<int, PhotonView> kvp in this.photonViewList) { PhotonView view = kvp.Value; if (view == null) { removeKeys.Add(kvp.Key); } } for (int index = 0; index < removeKeys.Count; index++) { int key = removeKeys[index]; this.photonViewList.Remove(key); } if (removeKeys.Count > 0) { if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(«New level loaded. Removed « + removeKeys.Count + « scene view IDs from last level.«); } } // this is called by Update() and in Unity that means it’s single threaded. public void RunViewUpdate() { if (!PhotonNetwork.connected || PhotonNetwork.offlineMode) { return; } if (this.mActors == null || #if !PHOTON_DEVELOP this.mActors.Count <= 1 #endif ) { return; // No need to send OnSerialize messages (these are never buffered anyway) } dataPerGroupReliable.Clear(); dataPerGroupUnreliable.Clear(); /* Format of the data hashtable: * Hasthable dataPergroup* * [(byte)0] = this.ServerTimeInMilliSeconds; * OPTIONAL: [(byte)1] = currentLevelPrefix; * + data */ foreach (KeyValuePair<int, PhotonView> kvp in this.photonViewList) { PhotonView view = kvp.Value; if (view.synchronization != ViewSynchronization.Off) { // Fetch all sending photonViews if (view.isMine) { #if UNITY_2_6_1 || UNITY_2_6 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 if (!view.gameObject.active) { continue; // Only on actives } #else if (!view.gameObject.activeInHierarchy) { continue; // Only on actives } #endif if (this.blockSendingGroups.Contains(view.group)) { continue; // Block sending on this group } // Run it trough its OnSerialize Hashtable evData = this.OnSerializeWrite(view); if (evData == null) { continue; } if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed || view.mixedModeIsReliable) { if (!evData.ContainsKey((byte)1) && !evData.ContainsKey((byte)2)) { // Everything has been removed by compression, nothing to send } else { if (!dataPerGroupReliable.ContainsKey(view.group)) { dataPerGroupReliable[view.group] = new Hashtable(); dataPerGroupReliable[view.group][(byte)0] = this.ServerTimeInMilliSeconds; if (currentLevelPrefix >= 0) { dataPerGroupReliable[view.group][(byte)1] = this.currentLevelPrefix; } } Hashtable groupHashtable = dataPerGroupReliable[view.group]; groupHashtable.Add((short)groupHashtable.Count, evData); } } else { if (!dataPerGroupUnreliable.ContainsKey(view.group)) { dataPerGroupUnreliable[view.group] = new Hashtable(); dataPerGroupUnreliable[view.group][(byte)0] = this.ServerTimeInMilliSeconds; if (currentLevelPrefix >= 0) { dataPerGroupUnreliable[view.group][(byte)1] = this.currentLevelPrefix; } } Hashtable groupHashtable = dataPerGroupUnreliable[view.group]; groupHashtable.Add((short)groupHashtable.Count, evData); } } else { // Debug.Log(» NO OBS on » + view.name + » » + view.owner); } } else { } } //Send the messages: every group is send in it’s own message and unreliable and reliable are split as well RaiseEventOptions options = new RaiseEventOptions(); #if PHOTON_DEVELOP options.Receivers = ReceiverGroup.All; #endif foreach (KeyValuePair<int, Hashtable> kvp in dataPerGroupReliable) { options.InterestGroup = (byte)kvp.Key; this.OpRaiseEvent(PunEvent.SendSerializeReliable, kvp.Value, true, options); } foreach (KeyValuePair<int, Hashtable> kvp in dataPerGroupUnreliable) { options.InterestGroup = (byte)kvp.Key; this.OpRaiseEvent(PunEvent.SendSerialize, kvp.Value, false, options); } } // calls OnPhotonSerializeView (through ExecuteOnSerialize) // the content created here is consumed by receivers in: ReadOnSerialize private Hashtable OnSerializeWrite(PhotonView view) { PhotonStream pStream = new PhotonStream( true, null ); PhotonMessageInfo info = new PhotonMessageInfo( this.mLocalActor, this.ServerTimeInMilliSeconds, view ); // each view creates a list of values that should be sent view.SerializeView( pStream, info ); if( pStream.Count == 0 ) { return null; } object[] dataArray = pStream.data.ToArray(); if (view.synchronization == ViewSynchronization.UnreliableOnChange) { if (AlmostEquals(dataArray, view.lastOnSerializeDataSent)) { if (view.mixedModeIsReliable) { return null; } view.mixedModeIsReliable = true; view.lastOnSerializeDataSent = dataArray; } else { view.mixedModeIsReliable = false; view.lastOnSerializeDataSent = dataArray; } } // EVDATA: // 0=View ID (an int, never compressed cause it’s not in the data) // 1=data of observed type (different per type of observed object) // 2=compressed data (in this case, key 1 is empty) // 3=list of values that are actually null (if something was changed but actually IS null) Hashtable evData = new Hashtable(); evData[(byte)0] = (int)view.viewID; evData[(byte)1] = dataArray; // this is the actual data (script or observed object) if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed) { // compress content of data set (by comparing to view.lastOnSerializeDataSent) // the «original» dataArray is NOT modified by DeltaCompressionWrite // if something was compressed, the evData key 2 and 3 are used (see above) bool somethingLeftToSend = this.DeltaCompressionWrite(view, evData); // buffer the full data set (for next compression) view.lastOnSerializeDataSent = dataArray; if (!somethingLeftToSend) { return null; } } return evData; } /// <summary> /// Reads updates created by OnSerializeWrite /// </summary> private void OnSerializeRead(Hashtable data, PhotonPlayer sender, int networkTime, short correctPrefix) { // read view ID from key (byte)0: a int-array (PUN 1.17++) int viewID = (int)data[(byte)0]; PhotonView view = this.GetPhotonView(viewID); if (view == null) { Debug.LogWarning(«Received OnSerialization for view ID « + viewID + «. We have no such PhotonView! Ignored this if you’re leaving a room. State: « + this.State); return; } if (view.prefix > 0 && correctPrefix != view.prefix) { Debug.LogError(«Received OnSerialization for view ID « + viewID + « with prefix « + correctPrefix + «. Our prefix is « + view.prefix); return; } // SetReceiving filtering if (view.group != 0 && !this.allowedReceivingGroups.Contains(view.group)) { return; // Ignore group } if (view.synchronization == ViewSynchronization.ReliableDeltaCompressed) { if (!this.DeltaCompressionRead(view, data)) { // Skip this packet as we haven’t got received complete-copy of this view yet. if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational) Debug.Log(«Skipping packet for « + view.name + « [« + view.viewID + «] as we haven’t received a full packet for delta compression yet. This is OK if it happens for the first few frames after joining a game.«); return; } // store last received for delta-compression usage view.lastOnSerializeDataReceived = data[(byte)1] as object[]; } if (sender.ID != view.ownerId) { if (!view.isSceneView || !sender.isMasterClient) { // obviously the owner changed and we didn’t yet notice. Debug.Log(«Adjusting owner to sender of updates. From: « + view.ownerId + « to: « + sender.ID); view.ownerId = sender.ID; } } object[] contents = data[(byte)1] as object[]; PhotonStream pStream = new PhotonStream(false, contents); PhotonMessageInfo info = new PhotonMessageInfo(sender, networkTime, view); view.DeserializeView( pStream, info ); } private bool AlmostEquals(object[] lastData, object[] currentContent) { if (lastData == null && currentContent == null) { return true; } if (lastData == null || currentContent == null || (lastData.Length != currentContent.Length)) { return false; } for (int index = 0; index < currentContent.Length; index++) { object newObj = currentContent[index]; object oldObj = lastData[index]; if (!this.ObjectIsSameWithInprecision(newObj, oldObj)) { return false; } } return true; } /// <summary> /// Compares the new data with previously sent data and skips values that didn’t change. /// </summary> /// <returns>True if anything has to be sent, false if nothing new or no data</returns> private bool DeltaCompressionWrite(PhotonView view, Hashtable data) { if (view.lastOnSerializeDataSent == null) { return true; // all has to be sent } // We can compress as we sent a full update previously (readers can re-use previous values) object[] lastData = view.lastOnSerializeDataSent; object[] currentContent = data[(byte)1] as object[]; if (currentContent == null) { // no data to be sent return false; } if (lastData.Length != currentContent.Length) { // if new data isn’t same length as before, we send the complete data-set uncompressed return true; } object[] compressedContent = new object[currentContent.Length]; int compressedValues = 0; List<int> valuesThatAreChangedToNull = new List<int>(); for (int index = 0; index < compressedContent.Length; index++) { object newObj = currentContent[index]; object oldObj = lastData[index]; if (this.ObjectIsSameWithInprecision(newObj, oldObj)) { // compress (by using null, instead of value, which is same as before) compressedValues++; // compressedContent[index] is already null (initialized) } else { compressedContent[index] = currentContent[index]; // value changed, we don’t replace it with null // new value is null (like a compressed value): we have to mark it so it STAYS null instead of being replaced with previous value if (newObj == null) { valuesThatAreChangedToNull.Add(index); } } } // Only send the list of compressed fields if we actually compressed 1 or more fields. if (compressedValues > 0) { data.Remove((byte)1); // remove the original data (we only send compressed data) if (compressedValues == currentContent.Length) { // all values are compressed to null, we have nothing to send return false; } data[(byte)2] = compressedContent; // current, compressted data is moved to key 2 to mark it as compressed if (valuesThatAreChangedToNull.Count > 0) { data[(byte)3] = valuesThatAreChangedToNull.ToArray(); // data that is actually null (not just cause we didn’t want to send it) } } return true; // some data was compressed but we need to send something } /// <summary> /// reads incoming messages created by «OnSerialize» /// </summary> private bool DeltaCompressionRead(PhotonView view, Hashtable data) { if (data.ContainsKey((byte)1)) { // we have a full list of data (cause key 1 is used), so return «we have uncompressed all» return true; } // Compression was applied as data[(byte)2] exists (this is the data with some fields being compressed to null) // now we also need a previous «full» list of values to restore values that are null in this msg if (view.lastOnSerializeDataReceived == null) { return false; // We dont have a full match yet, we cannot work with missing values: skip this message } object[] compressedContents = data[(byte)2] as object[]; if (compressedContents == null) { // despite expectation, there is no compressed data in this msg. shouldn’t happen. just a null check return false; } int[] indexesThatAreChangedToNull = data[(byte)3] as int[]; if (indexesThatAreChangedToNull == null) { indexesThatAreChangedToNull = new int[0]; } object[] lastReceivedData = view.lastOnSerializeDataReceived; for (int index = 0; index < compressedContents.Length; index++) { if (compressedContents[index] == null && !indexesThatAreChangedToNull.Contains(index)) { // we replace null values in this received msg unless a index is in the «changed to null» list object lastValue = lastReceivedData[index]; compressedContents[index] = lastValue; } } data[(byte)1] = compressedContents; // compressedContents are now uncompressed… return true; } /// <summary> /// Returns true if both objects are almost identical. /// Used to check whether two objects are similar enough to skip an update. /// </summary> bool ObjectIsSameWithInprecision(object one, object two) { if (one == null || two == null) { return one == null && two == null; } if (!one.Equals(two)) { // if A is not B, lets check if A is almost B if (one is Vector3) { Vector3 a = (Vector3)one; Vector3 b = (Vector3)two; if (a.AlmostEquals(b, PhotonNetwork.precisionForVectorSynchronization)) { return true; } } else if (one is Vector2) { Vector2 a = (Vector2)one; Vector2 b = (Vector2)two; if (a.AlmostEquals(b, PhotonNetwork.precisionForVectorSynchronization)) { return true; } } else if (one is Quaternion) { Quaternion a = (Quaternion)one; Quaternion b = (Quaternion)two; if (a.AlmostEquals(b, PhotonNetwork.precisionForQuaternionSynchronization)) { return true; } } else if (one is float) { float a = (float)one; float b = (float)two; if (a.AlmostEquals(b, PhotonNetwork.precisionForFloatSynchronization)) { return true; } } // one does not equal two return false; } return true; } internal protected static bool GetMethod(MonoBehaviour monob, string methodType, out MethodInfo mi) { mi = null; if (monob == null || string.IsNullOrEmpty(methodType)) { return false; } List<MethodInfo> methods = SupportClass.GetMethods(monob.GetType(), null); for (int index = 0; index < methods.Count; index++) { MethodInfo methodInfo = methods[index]; if (methodInfo.Name.Equals(methodType)) { mi = methodInfo; return true; } } return false; } /// <summary>Internally used to flag if the message queue was disabled by a «scene sync» situation (to re-enable it).</summary> internal protected bool loadingLevelAndPausedNetwork = false; /// <summary>For automatic scene syncing, the loaded scene is put into a room property. This is the name of said prop.</summary> internal protected const string CurrentSceneProperty = «curScn«; /// <summary>Internally used to detect the current scene and load it if PhotonNetwork.automaticallySyncScene is enabled.</summary> internal protected void LoadLevelIfSynced() { if (!PhotonNetwork.automaticallySyncScene || PhotonNetwork.isMasterClient || PhotonNetwork.room == null) { return; } // check if «current level» is set in props if (!PhotonNetwork.room.customProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty)) { return; } // if loaded level is not the one defined my master in props, load that level object sceneId = PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty]; if (sceneId is int) { if (Application.loadedLevel != (int)sceneId) PhotonNetwork.LoadLevel((int)sceneId); } else if (sceneId is string) { if (Application.loadedLevelName != (string)sceneId) PhotonNetwork.LoadLevel((string)sceneId); } } protected internal void SetLevelInPropsIfSynced(object levelId) { if (!PhotonNetwork.automaticallySyncScene || !PhotonNetwork.isMasterClient || PhotonNetwork.room == null) { return; } if (levelId == null) { Debug.LogError(«Parameter levelId can’t be null!«); return; } // check if «current level» is already set in props if (PhotonNetwork.room.customProperties.ContainsKey(NetworkingPeer.CurrentSceneProperty)) { object levelIdInProps = PhotonNetwork.room.customProperties[NetworkingPeer.CurrentSceneProperty]; if (levelIdInProps is int && Application.loadedLevel == (int)levelIdInProps) { return; } if (levelIdInProps is string && Application.loadedLevelName.Equals((string)levelIdInProps)) { return; } } // current level is not yet in props, so this client has to set it Hashtable setScene = new Hashtable(); if (levelId is int) setScene[NetworkingPeer.CurrentSceneProperty] = (int)levelId; else if (levelId is string) setScene[NetworkingPeer.CurrentSceneProperty] = (string)levelId; else Debug.LogError(«Parameter levelId must be int or string!«); PhotonNetwork.room.SetCustomProperties(setScene); this.SendOutgoingCommands(); // send immediately! because: in most cases the client will begin to load and not send for a while } public void SetApp(string appId, string gameVersion) { this.mAppId = appId.Trim(); if (!string.IsNullOrEmpty(gameVersion)) { this.mAppVersion = gameVersion.Trim(); } } public bool WebRpc(string uriPath, object parameters) { Dictionary<byte, object> opParameters = new Dictionary<byte, object>(); opParameters.Add(ParameterCode.UriPath, uriPath); opParameters.Add(ParameterCode.WebRpcParameters, parameters); return this.OpCustom(OperationCode.WebRpc, opParameters, true); } }

Local folder or tarball paths

This section provides information on the following issues:

Type of error: Error message:
General startup issues — Error messages in the Package Manager window
— Package Manager missing or window doesn’t open
— Problems after upgrading Unity to new version
— Resetting your project’s package configuration
Package installation issues — Package installation fails
— Packages not recognized
— Unable to add package from Git URL
Problems installing git dependencies — No ‘git’ executable was found
— git-lfs: command not found
— Repository not found
— Could not read Username: terminal prompts disabled
— Can’t update Git version
Asset StoreA growing library of free and commercial assets created by Unity and members of the community. Offers a wide variety of assets, from textures, models and animations to whole project examples, tutorials and Editor extensions. More info
See in Glossary
packages (My Assets)
— ‘Failed to parse Http response’ in My Assets context
Scoped registries — Missing ‘My Registries’ in the Package Manager window
Issues when building packages — Missing MonoBehaviour errors
— Loading error for hostfxr.dll on Windows

You can also run the Unity Package Manager Diagnostics tool if you are experiencing problems that might be network-related. For more information, see Diagnose network issues.

Error messages in the Package Manager window

The Package Manager displays error indicators in the Package Manager window when it encounters problems.

System-wide issues

  • Network connection issues

    Error messages appear in the status bar when the Package Manager has detected an issue that isn’t related to a specific package. For example, if the Package Manager can’t access the package registry server, it displays this message in the status bar:

    Network error message

    Network error message
  • Error refreshing assets (or Error refreshing packages)

    If your network can’t reach the package registry server, it’s probably because there is a connection problem with the network. When you or your system administrator diagnose and fix the network error, the status bar clears.

    If your network connection is working, but you aren’t signed into your Unity account, the Package Manager doesn’t display any Asset Store packages. When you try to use the My Assets context, the Package Manager displays an error in the status bar:

    Logged out of Unity account

    Logged out of Unity account

    Click the Sign in button inside the list view to sign into your Unity account through the Unity Hub.

Package-specific issues

  • If a specific package has a problem when loading or installing (for example, when determining which package versions to load), the error icon () appears in the package list next to the compromised package (A). To find out what the problem is, open the compromised package’s details view to see the detailed error message (B):

    Dependency error message

    Dependency error message

Package Manager missing or window doesn’t open

The Package Manager window might get moved offscreen or hidden by another window. When this happens, it looks like the Package Manager window failed to open. In this case, you can try to reset the window layout (Window > Layouts > Default) and reopen the Package Manager window again.

If the Package Manager window still doesn’t appear, check your Unity Console windowA Unity Editor window that shows errors, warnings and other messages generated by Unity, or your own scripts. More info
See in Glossary
:

Failed to resolve packages: The file [<project-path>/Packages/manifest.json] is not valid JSON:
  Unexpected token '}' at 44:1
  }

This error message indicates that your manifest.json file is malformed. It also tells you the line number where the Package Manager failed to parse the file, so you can fix the JSON. There are a number of online validators that you can use to try to correct the problem. Once you save the corrected file, Unity reloads the Package Manager window.

If you upgraded from an early version of the Unity Editor, there may be other problems with your package manifestEach package has a manifest, which provides information about the package to the Package Manager. The manifest contains information such as the name of the package, its version, a description for users, dependencies on other packages (if any), and other details. More info
See in Glossary
file:

  • As of 2019.3, your manifest.json file should not contain any references to the com.unity.package-manager-ui package. You can either reset your project’s package configuration or remove the following line from the manifest’s dependencies list:

        "com.unity.package-manager-ui": "2.1.1",
    
  • Check to see if your project manifestEach Unity project has a project manifest, which acts as an entry point for the Package Manager. This file must be available in the <project>/Packages directory. The Package Manager uses it to configure many things, including a list of dependencies for that project, as well as any package repository to query for packages. More info
    See in Glossary
    uses “exclude” as a package version. This is an obsolete value for the dependencies property. If you find any lines like these, remove the entire line. Package Manager only installs packages that are explicitly included as a dependency in your project, so once you remove that entry, Package Manager ignores the package and doesn’t install it.

If the Package Manager still fails to load, follow the procedures under Packages not recognized and Resetting your project’s package configuration.

Problems after upgrading Unity to new version

When you upgrade a project to a newer Unity version, the Package Manager automatically updates incompatible packages to newer compatible versions. However, if your package doesn’t compile, the Package Manager displays error messages in the Console.

To correct these messages, read the error messages and fix any problems you can. For example, a package might be missing a dependency on another package or version. In that case, you can try and install the package yourself.

You can also try the following sequence of solutions until you find something that works:

  • Back up and then delete the Packages folder under your project.
  • Back up and then delete the package sources in your project’s Packages folder, leaving only the manifest.json file. Then try to reload the project.
  • Create a new empty project. If the Package Manager window loads successfully, replace the Library/PackageCache/com.unity.package-manager-ui@<version> folder in the failing project with the same folder from the newly created project.
  • As a last resort, you can reset your project to the default packageUnity automatically pre-installs a select number of default packages (for example, the Analytics Library, Unity Timeline, etc.) when you create a new project. This differs from a bundled package because you don’t need to install it and it differs from a built-in package because it extends Unity’s features rather than being able to enable or disable them.
    See in Glossary
    configuration and add back packages one at a time until it works.

Resetting your project’s package configuration

If a project has too many package issues, you can reset your project back to the default package configuration for the Editor’s version of Unity. This operation resets all packages in your project. This might not fix the source of the problem, but it can help you figure out what the problem is.

Note: You can’t undo resetting your package configuration, so make sure you back up the manifest.json file first or make sure your project is under source control. You can also take extra precautions by cloning your project and testing out the operation on the clone before proceeding.

To return to the default package configuration, select Reset Packages to defaults from the Help menu.

Help > Reset Packages to defaults

Help > Reset Packages to defaults

Resetting a clone of your project

You can also test the return to the default packages before you perform the final change:

  1. Clone your project by copy-pasting your project folder and renaming it so that it is easy to find (for example, if your project is called MyProject then you could use something like clone_MyProject).

  2. Load your newly cloned project.

  3. From the Help menu, select Reset Packages to defaults.

    Depending on the size of your project, this might take a few minutes.

  4. Check that it successfully reset the packages. If so, you can perform the operation safely on the original project.

Package installation fails

If you are trying to install a new package from the registry and it is not working, it might be due to permission problems.

You must have full permissions on the cache folder:

  • Windows: C:UsersyournameAppDataLocalUnitycache
  • macOS: ~/Library/Unity/cache
  • Linux: ~/.config/unity3d/cache

It might be a problem with the network. Check your firewall and proxy settings.

Sometimes institutional environments, such as schools, government offices, or network-protected workplaces set up proxy servers to control traffic between the network and the Internet, and use their own server certificates which are not recognized by Unity or the Package Manager. Talk to your network administrator.

Packages not recognized

If you see a lot of compilation errors, this might indicate that Unity is not recognizing the packages in your existing project. In this case, you might be missing a .NET component.

For Windows:

  1. Download and install Visual Studio 2017 version 15.9.0 or higher with the .NET Core cross-platform development workload selected under Other Toolsets.
  2. Download and install the .NET SDK v2.2.101 component.

For MacOS:

  1. Download and install the .NET SDK v2.2.101 component.

  2. Install any recommended updates in Visual Studio

  3. Use homebrew to brew and install mono:

    brew update
    brew install mono # optional
    brew upgrade mono
    
  4. If necessary, delete the Library/obj/temp folder under your project and restart Unity.

  5. If you are still experiencing difficulties, try rebooting your computer as well.

Unable to add package from Git URL

See Repository not found.

No ‘git’ executable was found

If you try to install a package from a git URL, a message similar to this appears:

Cannot perform upm operation: Unable to add package
[https://github.example.com/myuser/myrepository.git]:
No 'git' executable was found. Please install Git on your system and restart Unity [NotFound]
UnityEditor.EditorApplication:Internal_CallUpdateFunctions()

git-lfs: command not found

If you are trying to download a package that uses Git LFS (Large File Storage), you might see this error message:

Error when executing git command. git-lfs filter-process: command not found.

This indicates that Git LFS is probably not installed on your machine. To make sure, you could test it on the command line:

git lfs --version

If you see something like this, Git LFS is installed:

git-lfs/2.8.0 (GitHub; darwin amd64; go 1.12.7)

Otherwise, you can install it by following the Bitbucket GitHub instructions.

Repository not found

If you specify a location that does not exist, a message similar to this one appears in the Unity Console:

Cannot perform upm operation: Unable to add package [https://mycompany.github.com/gitproject/com.mycompany.mypackage.git]:
  Error when executing git command. fatal: repository 'https://mycompany.github.com/gitproject/com.mycompany.mypackage.git/' not found
 [NotFound]
UnityEditor.EditorApplication:Internal_CallUpdateFunctions() (at /Users/builduser/buildslave/unity/build/Editor/Mono/EditorApplication.cs:310)

Check your spelling. To make sure you are using the correct URL, go to the repository’s page and copy the URL from the Clone button:

Where to copy the URL on GitHub (A) and GitLab (B)

Where to copy the URL on GitHub (A) and GitLab (B)

Click the button to the right of the URL on GitHub (A) or GitLab (B) to copy the URL to your clipboard.

If the location of the repository is correct, there may be another problem with the URL:

  • If you are targeting a specific revision, make sure your revision comes last. For example:
    https://github.example.com/myuser/myrepository1.git#revision
  • If you are targeting a revision and the package is not at the root, make sure the path query parameter precedes the revision anchor. For example:
    https://github.example.com/myuser/myrepository.git?path=/example/folder#v1.2.3

Could not read Username: terminal prompts disabled

If you are trying to install a package from a private repository that requires authentication, a message similar to this one appears in the Unity Console:

Cannot perform upm operation: Unable to add package [https://mycompany.github.com/gitproject/com.mycompany.mypackage.git]:
  Error when executing git command. fatal: could not read Username for 'https://mycompany.github.com': terminal prompts disabled
 [NotFound]
UnityEditor.EditorApplication:Internal_CallUpdateFunctions() (at /Users/builduser/buildslave/unity/build/Editor/Mono/EditorApplication.cs:310)

This message is likely due to the fact that Package Manager does not provide an interactive terminal or dialog where you can enter your username and password for HTTP, or your passphrase to unlock your SSH key:

  • With HTTP(S), every time you log onto BitBucket, GitHub or GitLab you need to enter your username and password in a terminal or a dialog box. However, the Package Manager does not provide an interactive terminal or dialog where you can enter your username and password for HTTP(S).

    To bypass this, use one of the workarounds suggested in Solutions for HTTPS.

  • SSH uses a pair of public and private SSH keys. You can add your public SSH key to Bitbucket, GitHub or GitLab and then access repositories without having to enter a username and password.

    However, if you have set up a passphrase to keep your SSH key safe, you still have to enter that passphrase in a terminal or a dialog box in order to authorize your key. In that case, you can use an SSH agent that can unlock your SSH key to authenticate with the Package Manager on your behalf.

Solutions for HTTPS

The Package Manager does not provide an interactive terminal or dialog where you can enter your HTTP(S) username and password. To bypass this, use one of these workarounds:

  • Use a credential manager (Git Credential Manager for Windows or OSXKeyChain). Credential managers handle sending the password without having to use a terminal or a command prompt.
  • Use git-credentials from a terminal or command prompt. Then launch the Hub from the same terminal so that Unity has access to the cached or stored credentials.
  • Use SSH to authenticate instead. If you set up your SSH key without a passphrase, the Package Manager doesn’t have to decrypt it in order to authenticate with the Git server. If you decide to use a passphrase for added security, you can still get around the authentication problem by using the ssh-agent on either macOS or Windows.

Solutions for SSH

If you are using the SSH protocol to install a package by Git URL, you might get an authentication error from Git. This typically happens when you set up a private SSH key on your local machine that is protected by a passphrase.

The solution to this problem is to set up an SSH agent that can unlock your SSH key to authenticate with the Package Manager on your behalf. Follow the instructions in the section that corresponds to your operating system:

  • Setting up OpenSSH for Windows
  • Adding SSH keys to your SSH Agent for macOS

Setting up OpenSSH for Windows

The native Windows OpenSSH version of the ssh-agent works better than the version available by default with Git for Windows. This procedure explains how to set up the OpenSSH client and add your key to its ssh-agent. If you are using Git for Windows, you can also prioritize the native Windows OpenSSH over the Git for Windows SSH agent:

  1. Make sure the OpenSSH Client is installed by searching for it in the Windows Settings Optional features window (Start > Settings, then search for “Optional features”). This applies to Windows 10+.

  2. Check your %PATH% environment variable to make sure the native Windows OpenSSH location appears (for example, C:WINDOWSSystem32OpenSSH).

    Note: If you are already using Git for Windows, make sure the native Windows OpenSSH location appears before the Git for Windows SSH location in your %PATH% variable. This ensures that Windows uses the native Windows OpenSSH agent over the Git for Windows SSH agent.

  3. In a PowerShell terminal, start the ssh-agent process and make sure it starts automatically:

    # Set the ssh-agent service to start automatically and manually start it now
    Get-Service ssh-agent | Set-Service -StartupType Automatic
    # Run the ssh-agent process to start the ssh-agent service
    ssh-agent
    
  4. Import your key into the ssh-agent by running ssh-add on the command line and then following the instructions. By default, the agent adds the %USERPROFILE%.sshid_rsa key and prompts you for the password.

    # Import the key
    ssh-add
    

    To use a different key, you can specify it as an argument:

    # Set the ssh-agent service to start automatically and manually start it now
    ssh-add <your-secure-ssh-key-name>
    

    If you can’t remember the name of your key, you can ask the agent to list them:

    ssh-add -l
    
  5. If you installed Git for Windows, reset the %GIT-SSH% environment variable to make sure that Git always uses the native Windows OpenSSH version of the ssh-agent:

    [Environment]::SetEnvironmentVariable("GIT_SSH", "$((Get-Command ssh).Source)", [System.EnvironmentVariableTarget]::User)
    

Adding SSH keys to your SSH Agent for macOS

Use the ssh-add command to add your SSH keys to the ssh-agent running on your macOS system. The command parameter you use depends on your version of macOS:

  • Prior to macOS 12, use:

    ssh-add -K ~/.ssh/<your-secure-ssh-key-name>
    
  • Starting with macOS 12, use:

    ssh-add --apple-use-keychain ~/.ssh/<your-secure-ssh-key-name>
    

After you run this command, the terminal asks for the password to unlock your SSH key and then adds it to the macOS keychain. However, once you restart your system, every key stored in the ssh-agent is reset.

To prevent re-entering your password after restarting your system, open the ~/.ssh/config file (or create one if you don’t find it), and add the following:

Host *
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/<your-secure-ssh-key-name>

Restart your machine to apply these changes.

Can’t update Git version

If you are trying to update your Git dependencyThe Package Manager retrieves Git dependencies from a Git repository directly rather than from a package registry. Git dependencies use a Git URL reference instead of a version, and there’s no guarantee about the package quality, stability, validity, or even whether the version stated in its package.json file respects Semantic Versioning rules with regards to officially published releases of this package. More info
See in Glossary
to a newer version from the repository, but it’s not working, it’s probably because your Git dependency is locked. If you want to update your Git dependency to a newer version from the repository, use the Add package from git URL button and enter a Git URL. For more information, see Locked Git dependencies.

‘Failed to parse Http response’ in My Assets context

If you see the following message in the Console window when trying to download an Asset Store package, there might be a problem with your Asset Store cache:

[PackageManager] Error Failed to parse response. UnityEditor.AsyncHTTPClient![:D](https://forum.unity.com/styles/default/xenforo/clear.png)one(State, Int32)

To solve this problem, delete all downloaded assets from the Asset Store package directory and then try downloading the assets again.

Warning: If your project contains a lot of asset data, this might take a lot of time and bandwidth to re-download everything.

Missing ‘My Registries’ in the Package Manager window

Not all registry providers are compatible with Unity’s Package Manager. If the package registry server you added does not implement the /-/v1/search or /-/all endpoints, your scoped registry is not compatible with Unity’s Package Manager, and doesn’t appear in the My Registries context in the Package Manager window.

Missing MonoBehaviour errors

While building, if there are a lot of errors about Missing Behavior, the UnityLinker might be mistakenly stripping out a component that it thinks is unreferenced. It often does this because the stripping level is too aggressive. For example, if you have a prefabAn asset type that allows you to store a GameObject complete with components and properties. The prefab acts as a template from which you can create new object instances in the scene. More info
See in Glossary
in an AssetBundle that references the SpriteShape component in the 2D SpriteShape package, the object might be missing and might generate compiler warnings.

To fix this, you can either lower the stripping level for the UnityLinker or declare the package’s assemblies inside the link.xml file in order to preserve them from being stripped:

<linker>
    <assembly fullname="Unity.2D.SpriteShape.Runtime" preserve="all"/>
    <assembly fullname="Unity.2D.Common.Runtime" preserve="all"/>
 </linker>

For more information on stripping levels and the UnityLinker, see Managed code stripping.

Loading error for hostfxr.dll on Windows

If the Console reports that the hostfxr.dll library was found, but Unity failed to load it from C:<path_to_app>hostfxr.dll, you can fix this error on Windows 7 or Windows Server 2008 R2 by installing both KB2999226 and KB2533623 patches.

Local folder or tarball paths

Подскажите плиз, что делать..

Вот код:

using System.Collections;
using UnityEngine;

public class Name : MonoBehaviour
{
    public string Url;
    public GUIText status;
    WebViewObject webViewObject;

    IEnumerator Start()
    {
        webViewObject = (new GameObject("WebViewObject")).AddComponent<WebViewObject>();
        webViewObject.Init(
            cb: (msg) =>
            {
                Debug.Log(string.Format("CallFromJS[{0}]", msg));
                status.text = msg;
                status.GetComponent<Animation>().Play(webViewObject);
            },
            err: (msg) =>
            {
                Debug.Log(string.Format("CallOnError[{0}]", msg));
                status.text = msg;
                status.GetComponent<Animation>().Play(webViewObject);
            },
            started: (msg) =>
            {
                Debug.Log(string.Format("CallOnStarted[{0}]", msg));
            },
            ld: (msg) =>
            {
                Debug.Log(string.Format("CallOnLoaded[{0}]", msg));
#if UNITY_EDITOR_OSX || !UNITY_ANDROID
                // NOTE: depending on the situation, you might prefer
                // the 'iframe' approach.
                // cf. https://github.com/gree/unity-webview/issues/189
#if true
                webViewObject.EvaluateJS(@"
                  if (window && window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.unityControl) {
                    window.Unity = {
                      call: function(msg) {
                        window.webkit.messageHandlers.unityControl.postMessage(msg);
                      }
                    }
                  } else {
                    window.Unity = {
                      call: function(msg) {
                        window.location = 'unity:' + msg;
                      }
                    }
                  }
                ");
#else
                webViewObject.EvaluateJS(@"
                  if (window && window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.unityControl) {
                    window.Unity = {
                      call: function(msg) {
                        window.webkit.messageHandlers.unityControl.postMessage(msg);
                      }
                    }
                  } else {
                    window.Unity = {
                      call: function(msg) {
                        var iframe = document.createElement('IFRAME');
                        iframe.setAttribute('src', 'unity:' + msg);
                        document.documentElement.appendChild(iframe);
                        iframe.parentNode.removeChild(iframe);
                        iframe = null;
                      }
                    }
                  }
                ");
#endif
#endif
                webViewObject.EvaluateJS(@"Unity.call('ua=' + navigator.userAgent)");
            },
            //ua: "custom user agent string",
            enableWKWebView: true);
#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX
        webViewObject.bitmapRefreshCycle = 1;
#endif
        webViewObject.SetMargins(5, 100, 5, Screen.height / 4);
        webViewObject.SetVisibility(true);

#if !UNITY_WEBPLAYER
        if (Url.StartsWith("http")) {
            webViewObject.LoadURL(Url.Replace(" ", "%20"));
        } else {
            var exts = new string[]{
                ".jpg",
                ".js",
                ".html"  // should be last
            };
            foreach (var ext in exts) {
                var url = Url.Replace(".html", ext);
                var src = System.IO.Path.Combine(Application.streamingAssetsPath, url);
                var dst = System.IO.Path.Combine(Application.persistentDataPath, url);
                byte[] result = null;
                if (src.Contains("://")) {  // for Android
                    var www = new WWW(src);
                    yield return www;
                    result = www.bytes;
                } else {
                    result = System.IO.File.ReadAllBytes(src);
                }
                System.IO.File.WriteAllBytes(dst, result);
                if (ext == ".html") {
                    webViewObject.LoadURL("file://" + dst.Replace(" ", "%20"));
                    break;
                }
            }
        }
#else
        if (Url.StartsWith("http")) {
            webViewObject.LoadURL(Url.Replace(" ", "%20"));
        } else {
            webViewObject.LoadURL("StreamingAssets/" + Url.Replace(" ", "%20"));
        }
        webViewObject.EvaluateJS(
            "parent.$(function() {" +
            "   window.Unity = {" +
            "       call:function(msg) {" +
            "           parent.unityWebView.sendMessage('WebViewObject', msg)" +
            "       }" +
            "   };" +
            "});");
#endif
        yield break;
    }

#if !UNITY_WEBPLAYER
    void OnGUI()
    {
        GUI.enabled = webViewObject.CanGoBack();
        if (GUI.Button(new Rect(10, 10, 80, 80), "<")) {
            webViewObject.GoBack();
        }
        GUI.enabled = true;

        GUI.enabled = webViewObject.CanGoForward();
        if (GUI.Button(new Rect(100, 10, 80, 80), ">")) {
            webViewObject.GoForward();
        }
        GUI.enabled = true;

        GUI.TextField(new Rect(200, 10, 300, 80), "" + webViewObject.Progress());
    }
#endif
}

Here are the examples of the csharp api UnityEngine.Debug.LogError(object) taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

[ImageEffectTransformsToLDR]
        private void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (CheckResources() == false)
            {
                Graphics.Blit(source, destination);
                return;
            }

#if UNITY_EDITOR
            validRenderTextureFormat = true;
            if (source.format != RenderTextureFormat.ARGBHalf)
            {
                validRenderTextureFormat = false;
            }
#endif

            // clamp some values to not go out of a valid range

            exposureAdjustment = exposureAdjustment < 0.001f ? 0.001f : exposureAdjustment;

            // SimpleReinhard tonemappers (local, non adaptive)

            if (type == TonemapperType.UserCurve)
            {
                float rangeScale = UpdateCurve();
                tonemapMaterial.SetFloat("_RangeScale", rangeScale);
                tonemapMaterial.SetTexture("_Curve", curveTex);
                Graphics.Blit(source, destination, tonemapMaterial, 4);
                return;
            }

            if (type == TonemapperType.SimpleReinhard)
            {
                tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
                Graphics.Blit(source, destination, tonemapMaterial, 6);
                return;
            }

            if (type == TonemapperType.Hable)
            {
                tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
                Graphics.Blit(source, destination, tonemapMaterial, 5);
                return;
            }

            if (type == TonemapperType.Photographic)
            {
                tonemapMaterial.SetFloat("_ExposureAdjustment", exposureAdjustment);
                Graphics.Blit(source, destination, tonemapMaterial, 8);
                return;
            }

            if (type == TonemapperType.OptimizedHejiDawson)
            {
                tonemapMaterial.SetFloat("_ExposureAdjustment", 0.5f*exposureAdjustment);
                Graphics.Blit(source, destination, tonemapMaterial, 7);
                return;
            }

            // still here?
            // =>  adaptive tone mapping:
            // builds an average log luminance, tonemaps according to
            // middle grey and white values (user controlled)

            // AdaptiveReinhardAutoWhite will calculate white value automagically

            bool freshlyBrewedInternalRt = CreateInternalRenderTexture(); // this retrieves rtFormat, so should happen before rt allocations

            RenderTexture rtSquared = RenderTexture.GetTemporary((int) adaptiveTextureSize, (int) adaptiveTextureSize, 0, rtFormat);
            Graphics.Blit(source, rtSquared);

            int downsample = (int) Mathf.Log(rtSquared.width*1.0f, 2);

            int div = 2;
            var rts = new RenderTexture[downsample];
            for (int i = 0; i < downsample; i++)
            {
                rts[i] = RenderTexture.GetTemporary(rtSquared.width/div, rtSquared.width/div, 0, rtFormat);
                div *= 2;
            }

            // downsample pyramid

            var lumRt = rts[downsample - 1];
            Graphics.Blit(rtSquared, rts[0], tonemapMaterial, 1);
            if (type == TonemapperType.AdaptiveReinhardAutoWhite)
            {
                for (int i = 0; i < downsample - 1; i++)
                {
                    Graphics.Blit(rts[i], rts[i + 1], tonemapMaterial, 9);
                    lumRt = rts[i + 1];
                }
            }
            else if (type == TonemapperType.AdaptiveReinhard)
            {
                for (int i = 0; i < downsample - 1; i++)
                {
                    Graphics.Blit(rts[i], rts[i + 1]);
                    lumRt = rts[i + 1];
                }
            }

            // we have the needed values, let's apply adaptive tonemapping

            adaptionSpeed = adaptionSpeed < 0.001f ? 0.001f : adaptionSpeed;
            tonemapMaterial.SetFloat("_AdaptionSpeed", adaptionSpeed);

            rt.MarkRestoreExpected(); // keeping luminance values between frames, RT restore expected

#if UNITY_EDITOR
            if (Application.isPlaying && !freshlyBrewedInternalRt)
                Graphics.Blit(lumRt, rt, tonemapMaterial, 2);
            else
                Graphics.Blit(lumRt, rt, tonemapMaterial, 3);
#else
			Graphics.Blit (lumRt, rt, tonemapMaterial, freshlyBrewedInternalRt ? 3 : 2);
#endif

            middleGrey = middleGrey < 0.001f ? 0.001f : middleGrey;
            tonemapMaterial.SetVector("_HdrParams", new Vector4(middleGrey, middleGrey, middleGrey, white*white));
            tonemapMaterial.SetTexture("_SmallTex", rt);
            if (type == TonemapperType.AdaptiveReinhard)
            {
                Graphics.Blit(source, destination, tonemapMaterial, 0);
            }
            else if (type == TonemapperType.AdaptiveReinhardAutoWhite)
            {
                Graphics.Blit(source, destination, tonemapMaterial, 10);
            }
            else
            {
                Debug.LogError("No valid adaptive tonemapper type found!");
                Graphics.Blit(source, destination); // at least we get the TransformToLDR effect
            }

            // cleanup for adaptive

            for (int i = 0; i < downsample; i++)
            {
                RenderTexture.ReleaseTemporary(rts[i]);
            }
            RenderTexture.ReleaseTemporary(rtSquared);
        }
public void Convert ( Texture2D temp2DTex, string path) {

            // conversion fun: the given 2D texture needs to be of the format
            //  w * h, wheras h is the 'depth' (or 3d dimension 'dim') and w = dim * dim

            if (temp2DTex) {
                int dim = temp2DTex.width * temp2DTex.height;
                dim = temp2DTex.height;

                if (!ValidDimensions(temp2DTex)) {
                    Debug.LogWarning ("The given 2D texture " + temp2DTex.name + " cannot be used as a 3D LUT.");
                    basedOnTempTex = "";
                    return;
                }

                var c = temp2DTex.GetPixels();
                var newC = new Color[c.Length];

                for(int i = 0; i < dim; i++) {
                    for(int j = 0; j < dim; j++) {
                        for(int k = 0; k < dim; k++) {
                            int j_ = dim-j-1;
                            newC[i + (j*dim) + (k*dim*dim)] = c[k*dim+i+j_*dim*dim];
                        }
                    }
                }

                if (converted3DLut)
                    DestroyImmediate (converted3DLut);
                converted3DLut = new Texture3D (dim, dim, dim, TextureFormat.ARGB32, false);
                converted3DLut.SetPixels (newC);
                converted3DLut.Apply ();
                basedOnTempTex = path;
            }
            else {
                // error, something went terribly wrong
                Debug.LogError ("Couldn't color correct with 3D LUT texture. Image Effect will be disabled.");
            }
        }
public bool Handle()
        {
            int count = hashData.Count;
            for (int i = 0; i < count; i++)
            {
                PhotonView view = PhotonView.Find(hashViews.Dequeue());
                if (view == null)
                {
                    //Message what view ID not exists
                    //Maybe put spam for invalid viewIDs, like 100 per second, idk
                    return true;
                }
                else if (view.prefix > 0 && correctPrefix != view.prefix)
                {
                    Debug.LogError(string.Concat(new object[] { "Received OnSerialization for view ID ", view.viewID, " with prefix ", correctPrefix, ". Our prefix is ", view.prefix }));
                }
                if (view.observed == null)
                {
                    myReason = $"OSR: Null observed for ViewID[{view.viewID.ToString()}]";
                    return false;
                }
                if (view.observed is MonoBehaviour)
                {
                    PhotonStream pStream = new PhotonStream(false, hashData.Dequeue());
                    PhotonMessageInfo info = new PhotonMessageInfo(sender, sentTime, view);
                    view.ExecuteOnSerialize(pStream, info);
                }
                else if (view.observed is Transform)
                {
                    Transform tf = (Transform)view.observed;
                    object[] arr = hashData.Dequeue();
                    switch (arr.Length)
                    {
                        case 1:
                            {
                                if (arr[0] == null || !(arr[0] is Vector3 vec))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                tf.localPosition = vec;
                            }
                            break;

                        case 2:
                            {
                                if (arr[0] == null || !(arr[0] is Vector3 vec))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                if (arr[1] == null || !(arr[1] is Quaternion quat))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                tf.localPosition = vec;
                                tf.localRotation = quat;
                                break;
                            }

                        case 3:
                        case 4:
                            {
                                if (arr[0] == null || !(arr[0] is Vector3 vec))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                if (arr[1] == null || !(arr[1] is Quaternion quat))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                if (arr[2] == null || !(arr[2] is Vector3 vec1))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                tf.localPosition = vec;
                                tf.localRotation = quat;
                                tf.localScale = vec1;
                                break;
                            }

                        default:
                            myReason = $"OSR:Invalid data length(Tf)" + arr.Length.ToString();
                            return false;
                    }
                }
                else if (view.observed is Rigidbody)
                {
                    Rigidbody rb = (Rigidbody)view.observed;
                    object[] arr = hashData.Dequeue();
                    switch (arr.Length)
                    {
                        case 1:
                            {
                                if (arr[0] == null || !(arr[0] is Vector3 vec))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                rb.velocity = vec;
                                break;
                            }

                        case 2:
                            {
                                if (arr[0] == null || !(arr[0] is Vector3 vec))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                if (arr[1] == null || !(arr[1] is Vector3 loc))
                                {
                                    myReason = "OSR: Null or Invalid value inside data";
                                    return false;
                                }
                                rb.velocity = vec;
                                rb.angularVelocity = loc;
                                break;
                            }

                        default:
                            myReason = "OSR:Invalid data length(Rb) " + arr.Length.ToString();
                            return false;
                    }
                }
                else
                {
                    //Log.Spam($"Recieved unknown observed type by [{sender.ID.ToString()}]", "UnkOSR", sender.ID);
                    hashData.Dequeue();
                }
            }
            return true;
        }
public bool Handle()
        {
            PhotonView photonView = PhotonView.Find(viewID);
            if (photonView == null)
            {
                return true;
            }
            if ((photonView.Group != 0) && !PhotonNetwork.networkingPeer.allowedReceivingGroups.Contains(photonView.Group))
            {
                return true;
            }
            System.Type[] callParameterTypes = new System.Type[0];
            if (parameters.Length > 0)
            {
                callParameterTypes = new System.Type[parameters.Length];
                int index = 0;
                for (int i = 0; i < parameters.Length; i++)
                {
                    object obj2 = parameters[i];
                    if (obj2 == null)
                    {
                        callParameterTypes[index] = null;
                    }
                    else
                    {
                        callParameterTypes[index] = obj2.GetType();
                    }
                    index++;
                }
            }
            int num7 = 0;
            int num8 = 0;
            foreach (MonoBehaviour behaviour in photonView.GetComponents<MonoBehaviour>())
            {
                if (behaviour == null)
                {
                    Debug.LogError("ERROR You have missing MonoBehaviours on your gameobjects!");
                }
                else
                {
                    System.Type key = behaviour.GetType();
                    List<MethodInfo> list = null;
                    if (PhotonNetwork.networkingPeer.monoRPCMethodsCache.ContainsKey(key))
                    {
                        list = PhotonNetwork.networkingPeer.monoRPCMethodsCache[key];
                    }
                    if (list == null)
                    {
                        List<MethodInfo> methods = SupportClreplaced.GetMethods(key, typeof(UnityEngine.RPC));
                        PhotonNetwork.networkingPeer.monoRPCMethodsCache[key] = methods;
                        list = methods;
                    }
                    if (list != null)
                    {
                        for (int j = 0; j < list.Count; j++)
                        {
                            MethodInfo info = list[j];
                            if (info.Name == name)
                            {
                                num8++;
                                ParameterInfo[] methodParameters = info.GetParameters();
                                if (methodParameters.Length == callParameterTypes.Length)
                                {
                                    if (PhotonNetwork.networkingPeer.CheckTypeMatch(methodParameters, callParameterTypes))
                                    {
                                        num7++;
                                        object obj3 = info.Invoke(behaviour, parameters);
                                        if (info.ReturnType == typeof(IEnumerator))
                                        {
                                            behaviour.StartCoroutine((IEnumerator)obj3);
                                        }
                                    }
                                    return true;
                                }
                                else if ((methodParameters.Length - 1) == callParameterTypes.Length)
                                {
                                    if (PhotonNetwork.networkingPeer.CheckTypeMatch(methodParameters, callParameterTypes) && (methodParameters[methodParameters.Length - 1].ParameterType == typeof(PhotonMessageInfo)))
                                    {
                                        num7++;
                                        object[] array = new object[parameters.Length + 1];
                                        parameters.CopyTo(array, 0);
                                        array[array.Length - 1] = new PhotonMessageInfo(sender, sTime, photonView);
                                        object obj4 = info.Invoke(behaviour, array);
                                        if (info.ReturnType == typeof(IEnumerator))
                                        {
                                            behaviour.StartCoroutine((IEnumerator)obj4);
                                        }
                                    }
                                    return true;
                                }
                                else if ((methodParameters.Length == 1) && methodParameters[0].ParameterType.IsArray)
                                {
                                    num7++;
                                    object[] objArray5 = new object[] { parameters };
                                    object obj5 = info.Invoke(behaviour, objArray5);
                                    if (info.ReturnType == typeof(IEnumerator))
                                    {
                                        behaviour.StartCoroutine((IEnumerator)obj5);
                                    }
                                    return true;
                                }
                                return false;
                            }
                            //Log.AddLineRaw("Unknown RPC: " + name + " by ID " + sender.ID);
                        }
                    }
                }
            }
            return true;
        }
public void Load()
        {
            if (!System.IO.File.Exists(Path))
            {
                Debug.LogError($"ConfigFile Error: There is no file {Path}.");
                return;
            }

            allValues.Clear();
            booleans.Clear();
            floats.Clear();
            integers.Clear();
            strings.Clear();
            string[] allStrings = System.IO.File.ReadAllLines(Path);
            foreach (string str in allStrings)
            {
                if (str.StartsWith("#") || str.Equals(string.Empty))
                {
                    continue;
                }
                string[] add = ParseString(str);
                if (add == null)
                {
                    continue;
                }
                allValues.Add(add[0], add[1]);
            }
        }
public static void SetLanguage(string lang)
        {
            if (AllLanguages.Contains(lang))
            {
                Directory = Path + lang + "/";
                SelectedLanguage = lang;
                Reload();
                return;
            }
            Debug.LogError("Not found language: " + lang);
            SetLanguage(DefaultLanguage);
        }
public bool Handle()
        {
            GameObject res = key.StartsWith("RCreplacedet/") ? CacheResources.RCLoad(key) : (GameObject)CacheResources.Load(key);
            if (res == null)
            {
                return false;
            }

            PhotonView[] photonViewsInChildren = res.GetPhotonViewsInChildren();
            if (photonViewsInChildren.Length != instIDs.Length)
            {
                throw new System.Exception("Error in Instantiation! The resource's PhotonView count is not the same as in incoming data.");
            }
            for (int i = 0; i < instIDs.Length; i++)
            {
                photonViewsInChildren[i].viewID = instIDs[i];
                photonViewsInChildren[i].prefix = prefix;
                photonViewsInChildren[i].instantiationId = instID;
            }
            PhotonNetwork.networkingPeer.StoreInstantiationData(instID, data);
            GameObject obj2 = (GameObject)UnityEngine.Object.Instantiate(res, position, rotation);
            for (int j = 0; j < instIDs.Length; j++)
            {
                photonViewsInChildren[j].viewID = 0;
                photonViewsInChildren[j].prefix = -1;
                photonViewsInChildren[j].prefixBackup = -1;
                photonViewsInChildren[j].instantiationId = -1;
            }
            PhotonNetwork.networkingPeer.RemoveInstantiationData(instID);
            if (PhotonNetwork.networkingPeer.instantiatedObjects.ContainsKey(instID))
            {
                GameObject go = PhotonNetwork.networkingPeer.instantiatedObjects[instID];
                string str2 = string.Empty;
                if (go != null)
                {
                    foreach (PhotonView view in go.GetPhotonViewsInChildren())
                    {
                        if (view != null)
                        {
                            str2 = str2 + view.ToString() + ", ";
                        }
                    }
                }
                object[] args = new object[] { obj2, instID, PhotonNetwork.networkingPeer.instantiatedObjects.Count, go, str2, PhotonNetwork.lastUsedViewSubId, PhotonNetwork.lastUsedViewSubIdStatic, NetworkingPeer.photonViewList.Count };
                Debug.LogError(string.Format("DoInstantiate re-defines a GameObject. Destroying old entry! New: '{0}' (instantiationID: {1}) Old: {3}. PhotonViews on old: {4}. instantiatedObjects.Count: {2}. PhotonNetwork.lastUsedViewSubId: {5} PhotonNetwork.lastUsedViewSubIdStatic: {6} photonViewList.Count {7}.)", args));
                PhotonNetwork.networkingPeer.RemoveInstantiatedGO(go, true);
            }
            PhotonNetwork.networkingPeer.instantiatedObjects.Add(instID, obj2);
            obj2.SendMessage(PhotonNetworkingMessage.OnPhotonInstantiate.ToString(), new PhotonMessageInfo(sender, timeStamp, null), SendMessageOptions.DontRequireReceiver);
            return true;
        }
private void Awake()
        {
            if (Instance != null)
            {
                Debug.LogError($"There should be only one instance of "UIManager". Please make sure yo spawn it just once.");
                DestroyImmediate(this);
                return;
            }
            DontDestroyOnLoad(this);
            Instance = this;
            onAwakeAdds();
            onAwakeRms();
            onAwakeAdds = delegate () { };
            onAwakeRms = delegate () { };
        }
[GUIPage(CreationPage)]
        private void RoomCreation()
        {
            left.Reset();
            right.Reset();
            LabelCenter(left, locale["roomSettings"], true);
            serverName = TextField(left, serverName, locale["roomName"], Style.LabelOffset, true);
            preplacedword = TextField(left, preplacedword, locale["pwd"], Style.LabelOffset, true);
            serverTime = TextField(left, serverTime, locale["time"], Style.LabelOffset * 2f, true);
            maxPlayers = TextField(left, maxPlayers, locale["players"], Style.LabelOffset * 2f, true);

            LabelCenter(left, locale["difficulity"], true);
            difficulity = SelectionGrid(left, difficulity, difficulities, difficulities.Length, true);

            LabelCenter(left, locale["dayLight"], true);
            daylight = SelectionGrid(left, daylight, daylights, daylights.Length, true);
            left.MoveY();

            LabelCenter(left, locale["presets"], true);
            Label(left, locale["presetNote"], true);
            newPresetName = TextField(left, newPresetName, locale["presetName"], Style.LabelOffset, true);
            left.width = (left.DefaultWidth - Style.HorizontalMargin) / 2f;
            if (Button(left, locale["presetAdd"], false))
            {
                ServerPreset set = new ServerPreset(newPresetName);
                ExportPreset(set);
                presets.Add(set);
                presetView.height = (presets.Count * Style.Height) + ((presets.Count - 1) * Style.VerticalMargin);
                set.Save();
            }
            left.MoveX();
            if (Button(left, locale["presetRemove"], true))
            {
                if (presets.Count > 1)
                {
                    ServerPreset selected = null;
                    for (int i = 0; i < presets.Count; i++)
                    {
                        if (presets[i].Name == newPresetName)
                        {
                            selected = presets[i];
                        }
                    }
                    if (selected != null)
                    {
                        presets.Remove(selected);
                        selected.Delete();
                        newPresetName = "Set " + (presets.Count + 1);
                        if (presets.Count > 0)
                        {
                            newPresetName = presets[presets.Count - 1].Name;
                        }

                        presetView.height = (presets.Count * Style.Height) + ((presets.Count - 1) * Style.VerticalMargin);
                    }
                }
            }
            left.ResetX();
            if (presets.Count > 0)
            {
                presetArea.y = left.y;
                presetRect.Reset();
                presetScroll = BeginScrollView(presetArea, presetScroll, presetView);
                {
                    for (int i = 0; i < presets.Count; i++)
                    {
                        if (Button(presetRect, presets[i].Name, true))
                        {
                            ServerPreset selected = presets[i];
                            ImportPreset(selected);
                        }
                    }
                }
                EndScrollView();
            }

            left.MoveToEndY(WindowPosition, Style.Height);
            left.width = left.DefaultWidth / 2f - Style.HorizontalMargin;
            if (Button(left, locale["btnCreation"], false))
            {
                disconnectByJoin = true;
                serverTime = serverTime.Trim();
                int serverTimeInt;
                if(!int.TryParse(serverTime, out serverTimeInt))
                {
                    serverTimeInt = 120;
                }

                daylight = daylight > 2 ? 0 : daylight;
                difficulity = difficulity > 2 ? 0 : difficulity;

                string mapName = string.Empty;

                try
                {
                    mapName = maps[mapSelectionSetting];
                }
                catch(System.Exception ex)
                {
                    Debug.LogError("Room creation exception appeared: " + ex.Message + "n" +  ex.StackTrace + $"nSetting info: {mapSelectionSetting}");
                    mapSelectionSetting.Value = 0;
                    mapName = maps[mapSelectionSetting.Value];
                }

                string[] args = new string[]
                {
                    serverName,
                    mapName,
                    new string[] { "normal", "hard", "abnormal" }[difficulity],
                    serverTimeInt.ToString(),
                    new string[] { "day", "dawn", "night" }[daylight],
                    preplacedword.Length > 0 ? new SimpleAES().Encrypt(preplacedword) : string.Empty,
                    UnityEngine.Random.Range(1000000, 10000000).ToString()
                };
                if (!int.TryParse(maxPlayers, out int max))
                {
                    max = 5;
                }
                PhotonNetwork.CreateRoom(string.Join("`", args), new RoomOptions() { isVisible = true, isOpen = true, maxPlayers = max }, null);
                DisableImmediate();
                AnarchyManager.Background.Disable();
                return;
            }
            left.MoveX(Style.HorizontalMargin, true);
            if (Button(left, locale["btnOffline"], false))
            {
                disconnectByJoin = true;
                PhotonNetwork.Disconnect();
                PhotonNetwork.offlineMode = true;
                string[] args = new string[]
                {
                    serverName,
                    maps[mapSelectionSetting.Value],
                    new string[] { "normal", "hard", "abnormal" }[difficulity],
                    serverTime,
                    new string[] { "day", "dawn", "night" }[daylight],
                    preplacedword.Length > 0 ? new SimpleAES().Encrypt(preplacedword) : string.Empty,
                    UnityEngine.Random.Range(1000000, 10000000).ToString()
                };
                if (!int.TryParse(maxPlayers, out int max))
                {
                    max = 5;
                }
                PhotonNetwork.CreateRoom(string.Join("`", args), new RoomOptions() { isVisible = true, isOpen = true, maxPlayers = max }, null);
                DisableImmediate();
                AnarchyManager.Background.Disable();
                return;
            }

            LabelCenter(right, locale["mapSelection"], true);
            //mapSelection = SelectionGrid(right, mapSelection, maps, 1);
            DropdownMenuScrollable(this, right, mapSelectionSetting, maps, 10, true);
            right.MoveY();
            right.MoveY();
            Label(right, LevelInfo.GetInfo(maps[mapSelectionSetting.Value], false).Description, true);
            right.MoveToEndY(WindowPosition, Style.Height);
            right.MoveToEndX(WindowPosition, new AutoScaleFloat(240f) + Style.HorizontalMargin);
            right.width = new AutoScaleFloat(120f);
            if (Button(right, locale["btnSettings"], false))
            {
                connected = false;
                pageSelection = SettingsPage;
                return;
            }
            right.MoveX();
            if (Button(right, locale["btnList"], false))
            {
                connected = PhotonNetwork.connected;
                if (connected)
                {
                    timeToUpdate = 0.1f;
                }
                pageSelection = ServerListPage;
                return;
            }
        }
private static int GetLayer(int layerToSet, string name)
        {
            lock (usedLayers)
            {
                if (layerToSet >= 0)
                {
                    if (usedLayers.Contains(layerToSet))
                    {
                        Debug.LogError($"Attemption to create GUIBase with already existing layer. Please make sure you wanted to use this one. Layer: {layerToSet}, GUIBase name: {name}");
                        return GetLayer(++layerToSet, name);
                    }
                    usedLayers.Add(layerToSet);
                    UpdateMaxLayer();
                    return layerToSet;
                }
                maxLayer = usedLayers.Max();
                usedLayers.Add(++maxLayer);
                return maxLayer;
            }
        }
public Texture2D LoadTexture(string namebase, string ext)
        {
            if (textureCache.TryGetValue(namebase, out Texture2D res) && res != null)
            {
                return res;
            }
            string name = namebase;
            bool error = false;
            if (ext == string.Empty)
            {
                if (!name.EndsWith(".png") && !name.EndsWith(".jpg") && !name.EndsWith(".jpeg"))
                {
                    error = true;
                }
            }
            else
            {
                if (!ext.Equals("png") && !ext.Equals("jpg") && !ext.Equals("jpeg"))
                {
                    error = true;
                }

                name += "." + ext;
            }
            if (error)
            {
                Debug.LogError($"You should use png, jpg or jpeg extensions for loading Texture2D");
                return Texture2D.blackTexture;
            }
            string path = Directory + name;
            if (!File.Exists(path))
            {
                Debug.LogError($"File what you are trying to load doesnt't exist: "{path}"");
                return Texture2D.blackTexture;
            }
            res = new Texture2D(1, 1, TextureFormat.RGBA32, false);
            res.LoadImage(File.ReadAllBytes(path));
            res.Apply();
            textureCache.Add(namebase, res);
            return res;
        }
public MovieTexture LoadVideo(string namebase)
        {
            MovieTexture tex;
            string name = namebase;
            string path = Directory + name + ".ogv";
            if (!File.Exists(path))
            {
                Debug.LogError($"File what you are trying to load doesnt't exist: "{path}"");
                return null;
            }
            WWW www = new WWW("file://" + path);
            if (www.texture == null)
            {
                Debug.LogError($"Null texture");
                www.Dispose();
                GC.SuppressFinalize(www);
                return null;
            }
            tex = www.movie;
            www.Dispose();
            GC.SuppressFinalize(www);
            return tex;
        }
public static System.Collections.IEnumerator LoadreplacedetBundle()
        {
            replacedetBundleCreateRequest bundle = replacedetBundle.CreateFromMemory(File.ReadAllBytes(BundlePath));
            yield return bundle;
            if (bundle == null)
            {
                Debug.LogError($"Error while loading Anarchyreplacedets. Make sure that file "{BundlePath}" exists.");
                yield break;
            }

            Bundle = bundle.replacedetBundle;
        }
[RPC]
    private void loadskinRPC(string url, PhotonMessageInfo info = null)
    {
        if (SkinSettings.replacedanSkins.Value == 1 && info != null && info.Sender.IsMasterClient && Anarchy.Network.Antis.IsValidSkinURL(ref url, 1, info.Sender.ID))
        {
            if (mySkin != null)
            {
                Debug.LogError($"Someone tries to reload existing {GetType().Name} skin");
                return;
            }
            StartCoroutine(LoadMySkin(url));
        }
    }
[RPC]
    private void loadskinRPC(string url, PhotonMessageInfo info = null)
    {
        if(SkinSettings.replacedanSkins.Value == 1 && info != null && info.Sender.IsMasterClient)
        {
            if(mySkin != null)
            {
                Debug.LogError($"Someone tries to reload existing {GetType().Name} skin");
                return;
            }
            StartCoroutine(LoadMySkin(url));
        }
    }
public void OnPhotonCreateRoomFailed(AOTEventArgs args)
    {
        Debug.LogError("OnPhotonCreateRoomFailed");
    }
private void Awake()
        {
            if (instance != null)
            {
                DestroyImmediate(this);
                Debug.LogError("Attemption to create more then one Anarchy.InputManager, please avoid this");
                return;
            }
            DontDestroyOnLoad(this);
            instance = this;
            if (AllKeys == null)
            {
                InitList();
            }

            onAwake?.Invoke();
            onAwake = null;
        }
public void MultiplayerRacingFinish()
    {
        Debug.LogError(nameof(MultiplayerRacingFinish));
        var num = logic.RoundTime - ((RacingLogic)logic).StartTime;
        if (PhotonNetwork.IsMasterClient)
        {
            getRacingResult(User.RaceName, num);
        }
        else
        {
            BasePV.RPC("getRacingResult", PhotonTargets.MasterClient, User.RaceName, num);
        }

        GameWin();
    }
public void Set(BetterList<Vector3> verts, BetterList<Vector3> norms, BetterList<Vector4> tans, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        int size = verts.size;
        if (size > 0 && size == uvs.size && size == cols.size && size % 4 == 0)
        {
            if (this.mFilter == null)
            {
                this.mFilter = base.gameObject.GetComponent<MeshFilter>();
            }
            if (this.mFilter == null)
            {
                this.mFilter = base.gameObject.AddComponent<MeshFilter>();
            }
            if (this.mRen == null)
            {
                this.mRen = base.gameObject.GetComponent<MeshRenderer>();
            }
            if (this.mRen == null)
            {
                this.mRen = base.gameObject.AddComponent<MeshRenderer>();
                this.UpdateMaterials();
            }
            else if (this.mClippedMat != null && this.mClippedMat.mainTexture != this.mSharedMat.mainTexture)
            {
                this.UpdateMaterials();
            }
            if (verts.size < 65000)
            {
                int num = (size >> 1) * 3;
                bool flag = this.mIndices == null || this.mIndices.Length != num;
                if (flag)
                {
                    this.mIndices = new int[num];
                    int num2 = 0;
                    for (int i = 0; i < size; i += 4)
                    {
                        this.mIndices[num2++] = i;
                        this.mIndices[num2++] = i + 1;
                        this.mIndices[num2++] = i + 2;
                        this.mIndices[num2++] = i + 2;
                        this.mIndices[num2++] = i + 3;
                        this.mIndices[num2++] = i;
                    }
                }
                Mesh mesh = this.GetMesh(ref flag, verts.size);
                mesh.vertices = verts.ToArray();
                if (norms != null)
                {
                    mesh.normals = norms.ToArray();
                }
                if (tans != null)
                {
                    mesh.tangents = tans.ToArray();
                }
                mesh.uv = uvs.ToArray();
                mesh.colors32 = cols.ToArray();
                if (flag)
                {
                    mesh.triangles = this.mIndices;
                }
                mesh.RecalculateBounds();
                this.mFilter.mesh = mesh;
            }
            else
            {
                if (this.mFilter.mesh != null)
                {
                    this.mFilter.mesh.Clear();
                }
                Debug.LogError("Too many vertices on one panel: " + verts.size);
            }
        }
        else
        {
            if (this.mFilter.mesh != null)
            {
                this.mFilter.mesh.Clear();
            }
            Debug.LogError("UIWidgets must fill the buffer with 4 vertices per quad. Found " + size);
        }
    }
public void Print(string text, Color32 color, BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols, bool encoding, UIFont.SymbolStyle symbolStyle, UIFont.Alignment alignment, int lineWidth, bool premultiply)
    {
        if (this.mReplacement != null)
        {
            this.mReplacement.Print(text, color, verts, uvs, cols, encoding, symbolStyle, alignment, lineWidth, premultiply);
        }
        else if (text != null)
        {
            if (!this.isValid)
            {
                Debug.LogError("Attempting to print using an invalid font!");
                return;
            }
            bool isDynamic = this.isDynamic;
            if (isDynamic)
            {
                this.mDynamicFont.textureRebuildCallback = new Font.FontTextureRebuildCallback(this.OnFontChanged);
                this.mDynamicFont.RequestCharactersInTexture(text, this.mDynamicFontSize, this.mDynamicFontStyle);
                this.mDynamicFont.textureRebuildCallback = null;
            }
            this.mColors.Clear();
            this.mColors.Add(color);
            int size = this.size;
            Vector2 vector = (size <= 0) ? Vectors.v2one : new Vector2(1f / (float)size, 1f / (float)size);
            int size2 = verts.size;
            int num = 0;
            int num2 = 0;
            int num3 = 0;
            int num4 = 0;
            int num5 = size + this.mSpacingY;
            Vector3 zero = Vectors.zero;
            Vector3 zero2 = Vectors.zero;
            Vector2 zero3 = Vectors.v2zero;
            Vector2 zero4 = Vectors.v2zero;
            float num6 = this.uvRect.width / (float)this.mFont.texWidth;
            float num7 = this.mUVRect.height / (float)this.mFont.texHeight;
            int length = text.Length;
            bool flag = encoding && symbolStyle != UIFont.SymbolStyle.None && this.hreplacedymbols && this.sprite != null;
            for (int i = 0; i < length; i++)
            {
                char c = text[i];
                if (c == 'n')
                {
                    if (num2 > num)
                    {
                        num = num2;
                    }
                    if (alignment != UIFont.Alignment.Left)
                    {
                        this.Align(verts, size2, alignment, num2, lineWidth);
                        size2 = verts.size;
                    }
                    num2 = 0;
                    num3 += num5;
                    num4 = 0;
                }
                else if (c < ' ')
                {
                    num4 = 0;
                }
                else
                {
                    if (encoding && c == '[')
                    {
                        int num8 = NGUITools.ParseSymbol(text, i, this.mColors, premultiply);
                        if (num8 > 0)
                        {
                            color = this.mColors[this.mColors.Count - 1];
                            i += num8 - 1;
                            goto IL_96C;
                        }
                    }
                    if (!isDynamic)
                    {
                        BMSymbol bmsymbol = (!flag) ? null : this.MatchSymbol(text, i, length);
                        if (bmsymbol == null)
                        {
                            BMGlyph glyph = this.mFont.GetGlyph((int)c);
                            if (glyph == null)
                            {
                                goto IL_96C;
                            }
                            if (num4 != 0)
                            {
                                num2 += glyph.GetKerning(num4);
                            }
                            if (c == ' ')
                            {
                                num2 += this.mSpacingX + glyph.advance;
                                num4 = (int)c;
                                goto IL_96C;
                            }
                            zero.x = vector.x * (float)(num2 + glyph.offsetX);
                            zero.y = -vector.y * (float)(num3 + glyph.offsetY);
                            zero2.x = zero.x + vector.x * (float)glyph.width;
                            zero2.y = zero.y - vector.y * (float)glyph.height;
                            zero3.x = this.mUVRect.xMin + num6 * (float)glyph.x;
                            zero3.y = this.mUVRect.yMax - num7 * (float)glyph.y;
                            zero4.x = zero3.x + num6 * (float)glyph.width;
                            zero4.y = zero3.y - num7 * (float)glyph.height;
                            num2 += this.mSpacingX + glyph.advance;
                            num4 = (int)c;
                            if (glyph.channel == 0 || glyph.channel == 15)
                            {
                                for (int j = 0; j < 4; j++)
                                {
                                    cols.Add(color);
                                }
                            }
                            else
                            {
                                Color color2 = color;
                                color2 *= 0.49f;
                                switch (glyph.channel)
                                {
                                    case 1:
                                        color2.b += 0.51f;
                                        break;

                                    case 2:
                                        color2.g += 0.51f;
                                        break;

                                    case 4:
                                        color2.r += 0.51f;
                                        break;

                                    case 8:
                                        color2.a += 0.51f;
                                        break;
                                }
                                for (int k = 0; k < 4; k++)
                                {
                                    cols.Add(color2);
                                }
                            }
                        }
                        else
                        {
                            zero.x = vector.x * (float)(num2 + bmsymbol.offsetX);
                            zero.y = -vector.y * (float)(num3 + bmsymbol.offsetY);
                            zero2.x = zero.x + vector.x * (float)bmsymbol.width;
                            zero2.y = zero.y - vector.y * (float)bmsymbol.height;
                            Rect uvRect = bmsymbol.uvRect;
                            zero3.x = uvRect.xMin;
                            zero3.y = uvRect.yMax;
                            zero4.x = uvRect.xMax;
                            zero4.y = uvRect.yMin;
                            num2 += this.mSpacingX + bmsymbol.advance;
                            i += bmsymbol.length - 1;
                            num4 = 0;
                            if (symbolStyle == UIFont.SymbolStyle.Colored)
                            {
                                for (int l = 0; l < 4; l++)
                                {
                                    cols.Add(color);
                                }
                            }
                            else
                            {
                                Color32 item = Color.white;
                                item.a = color.a;
                                for (int m = 0; m < 4; m++)
                                {
                                    cols.Add(item);
                                }
                            }
                        }
                        verts.Add(new Vector3(zero2.x, zero.y));
                        verts.Add(new Vector3(zero2.x, zero2.y));
                        verts.Add(new Vector3(zero.x, zero2.y));
                        verts.Add(new Vector3(zero.x, zero.y));
                        uvs.Add(new Vector2(zero4.x, zero3.y));
                        uvs.Add(new Vector2(zero4.x, zero4.y));
                        uvs.Add(new Vector2(zero3.x, zero4.y));
                        uvs.Add(new Vector2(zero3.x, zero3.y));
                    }
                    else if (this.mDynamicFont.GetCharacterInfo(c, out UIFont.mChar, this.mDynamicFontSize, this.mDynamicFontStyle))
                    {
                        zero.x = vector.x * ((float)num2 + UIFont.mChar.vert.xMin);
                        zero.y = -vector.y * ((float)num3 - UIFont.mChar.vert.yMax + this.mDynamicFontOffset);
                        zero2.x = zero.x + vector.x * UIFont.mChar.vert.width;
                        zero2.y = zero.y - vector.y * UIFont.mChar.vert.height;
                        zero3.x = UIFont.mChar.uv.xMin;
                        zero3.y = UIFont.mChar.uv.yMin;
                        zero4.x = UIFont.mChar.uv.xMax;
                        zero4.y = UIFont.mChar.uv.yMax;
                        num2 += this.mSpacingX + (int)UIFont.mChar.width;
                        for (int n = 0; n < 4; n++)
                        {
                            cols.Add(color);
                        }
                        if (UIFont.mChar.flipped)
                        {
                            uvs.Add(new Vector2(zero3.x, zero4.y));
                            uvs.Add(new Vector2(zero3.x, zero3.y));
                            uvs.Add(new Vector2(zero4.x, zero3.y));
                            uvs.Add(new Vector2(zero4.x, zero4.y));
                        }
                        else
                        {
                            uvs.Add(new Vector2(zero4.x, zero3.y));
                            uvs.Add(new Vector2(zero3.x, zero3.y));
                            uvs.Add(new Vector2(zero3.x, zero4.y));
                            uvs.Add(new Vector2(zero4.x, zero4.y));
                        }
                        verts.Add(new Vector3(zero2.x, zero.y));
                        verts.Add(new Vector3(zero.x, zero.y));
                        verts.Add(new Vector3(zero.x, zero2.y));
                        verts.Add(new Vector3(zero2.x, zero2.y));
                    }
                }
                IL_96C:;
            }
            if (alignment != UIFont.Alignment.Left && size2 < verts.size)
            {
                this.Align(verts, size2, alignment, num2, lineWidth);
                size2 = verts.size;
            }
        }
    }
public static void Broadcast(string funcName, object param)
    {
        if (param == null)
        {
            Debug.LogError("SendMessage is bugged when you try to preplaced 'null' in the parameter field. It behaves as if no parameter was specified.");
        }
        else
        {
            int i = 0;
            int count = UIRoot.mRoots.Count;
            while (i < count)
            {
                UIRoot uiroot = UIRoot.mRoots[i];
                if (uiroot != null)
                {
                    uiroot.BroadcastMessage(funcName, param, SendMessageOptions.DontRequireReceiver);
                }
                i++;
            }
        }
    }
public static WWW OpenURL(string url)
    {
        WWW result = null;
        try
        {
            result = new WWW(url);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex.Message);
        }
        return result;
    }
public static WWW OpenURL(string url, WWWForm form)
    {
        if (form == null)
        {
            return NGUITools.OpenURL(url);
        }
        WWW result = null;
        try
        {
            result = new WWW(url, form);
        }
        catch (Exception ex)
        {
            Debug.LogError((ex == null) ? "<null>" : ex.Message);
        }
        return result;
    }
public void AllocateManualPhotonView()
    {
        PhotonView photonView = base.gameObject.GetPhotonView();
        if (photonView == null)
        {
            Debug.LogError("Can't do manual instantiation without PhotonView component.");
            return;
        }
        int num = PhotonNetwork.AllocateViewID();
        photonView.RPC("InstantiateRpc", PhotonTargets.AllBuffered, new object[]
        {
            num
        });
    }
public void DebugReturn(DebugLevel level, string message)
    {
        if (level == DebugLevel.ERROR)
        {
            Debug.LogError(message);
        }
        else if (level == DebugLevel.WARNING)
        {
            Debug.LogWarning(message);
        }
        else if (level == DebugLevel.INFO && PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
        {
            Debug.Log(message);
        }
        else if (level == DebugLevel.ALL && PhotonNetwork.logLevel == PhotonLogLevel.Full)
        {
            Debug.Log(message);
        }
    }
private static bool VerifyCreplacedeNetwork()
    {
        if (connected)
        {
            return true;
        }
        Debug.LogError("Cannot send messages when not connected. Either connect to Photon OR use offline mode!");
        return false;
    }
internal static void RPC(PhotonView view, string methodName, PhotonPlayer targetPlayer, params object[] parameters)
    {
        if (!VerifyCreplacedeNetwork())
        {
            return;
        }
        if (room == null)
        {
            Debug.LogWarning("Cannot send RPCs in Lobby, only processed locally");
            return;
        }
        if (player == null)
        {
            Debug.LogError("Error; Sending RPC to player null! Aborted "" + methodName + """);
        }
        if (networkingPeer != null)
        {
            networkingPeer.RPC(view, methodName, targetPlayer, parameters);
        }
        else
        {
            Debug.LogWarning("Could not execute RPC " + methodName + ". Possible scene loading in progress?");
        }
    }
public static bool CloseConnection(PhotonPlayer kickPlayer)
    {
        if (!VerifyCreplacedeNetwork())
        {
            return false;
        }
        if (!player.IsMasterClient)
        {
            Debug.LogError("CloseConnection: Only the masterclient can kick another player.");
            return false;
        }
        if (kickPlayer == null)
        {
            Debug.LogError("CloseConnection: No such player connected!");
            return false;
        }
        RaiseEventOptions raiseEventOptions = new RaiseEventOptions
        {
            TargetActors = new int[]
            {
                kickPlayer.ID
            }
        };
        return networkingPeer.OpRaiseEvent(203, null, true, raiseEventOptions);
    }
public static bool ConnectUsingSettings(string gameVersion)
    {
        if (PhotonServerSettings == null)
        {
            Debug.LogError("Can't connect: Loading settings failed. ServerSettings replacedet must be in any 'Resources' folder as: PhotonServerSettings");
            return false;
        }
        SwitchToProtocol(PhotonServerSettings.Protocol);
        networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion);
        if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode)
        {
            offlineMode = true;
            return true;
        }
        if (offlineMode)
        {
            Debug.LogWarning("ConnectUsingSettings() disabled the offline mode. No longer offline.");
        }
        offlineMode = false;
        isMessageQueueRunning = true;
        networkingPeer.IsInitialConnect = true;
        if (PhotonServerSettings.HostType == ServerSettings.HostingOption.SelfHosted)
        {
            networkingPeer.IsUsingNameServer = false;
            networkingPeer.MasterServerAddress = PhotonServerSettings.ServerAddress + ":" + PhotonServerSettings.ServerPort;
            return networkingPeer.Connect(networkingPeer.MasterServerAddress, ServerConnection.MasterServer);
        }
        if (PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion)
        {
            return ConnectToBestCloudServer(gameVersion);
        }
        return networkingPeer.ConnectToRegionMaster(PhotonServerSettings.PreferredRegion);
    }
public static bool CreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby)
    {
        if (offlineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("CreateRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            offlineModeRoom = new Room(roomName, roomOptions);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom, new object[0]);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom, new object[0]);
            return true;
        }
        else
        {
            if (networkingPeer.server != ServerConnection.MasterServer || !connectedAndReady)
            {
                Debug.LogError("CreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
                return false;
            }
            return networkingPeer.OpCreateGame(roomName, roomOptions, typedLobby);
        }
    }
public static void Destroy(PhotonView targetView)
    {
        if (targetView != null)
        {
            networkingPeer.RemoveInstantiatedGO(targetView.gameObject, !inRoom);
        }
        else
        {
            Debug.LogError("Destroy(targetPhotonView) failed, cause targetPhotonView is null.");
        }
    }
public static void DestroyAll()
    {
        if (IsMasterClient)
        {
            networkingPeer.DestroyAll(false);
        }
        else
        {
            Debug.LogError("Couldn't call DestroyAll() as only the master client is allowed to call this.");
        }
    }
public static void DestroyPlayerObjects(PhotonPlayer targetPlayer)
    {
        if (targetPlayer == null)
        {
            Debug.LogError("DestroyPlayerObjects() failed, cause parameter 'targetPlayer' was null.");
        }
        DestroyPlayerObjects(targetPlayer.ID);
    }
public static void DestroyPlayerObjects(int targetPlayerId)
    {
        if (!VerifyCreplacedeNetwork())
        {
            return;
        }
        if (player.IsMasterClient || targetPlayerId == player.ID)
        {
            networkingPeer.DestroyPlayerObjects(targetPlayerId, false);
        }
        else
        {
            Debug.LogError("DestroyPlayerObjects() failed, cause players can only destroy their own GameObjects. A Master Client can destroy anyone's. This is master: " + IsMasterClient);
        }
    }
public static GameObject Instantiate(string prefabName, Vector3 position, Quaternion rotation, int group, object[] data)
    {
        if (!connected || (InstantiateInRoomOnly && !inRoom))
        {
            Debug.LogError(string.Concat(new object[]
            {
                "Failed to Instantiate prefab: ",
                prefabName,
                ". Client should be in a room. Current connectionStateDetailed: ",
                connectionStateDetailed
            }));
            return null;
        }
        GameObject gameObject = prefabName.StartsWith("RCreplacedet/") ? Optimization.Caching.CacheResources.RCLoad(prefabName) : (GameObject)Optimization.Caching.CacheResources.Load(prefabName);
        //      if (!UsePrefabCache || !PrefabCache.TryGetValue(prefabName, out gameObject))
        //{
        //	gameObject =
        //	if (UsePrefabCache)
        //	{
        //		PrefabCache.Add(prefabName, gameObject);
        //	}
        //}
        if (gameObject == null)
        {
            Debug.LogError("Failed to Instantiate prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)");
            return null;
        }
        if (gameObject.GetComponent<PhotonView>() == null)
        {
            Debug.LogError("Failed to Instantiate prefab:" + prefabName + ". Prefab must have a PhotonView component.");
            return null;
        }
        Component[] photonViewsInChildren = gameObject.GetPhotonViewsInChildren();
        int[] array = new int[photonViewsInChildren.Length];
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = AllocateViewID(player.ID);
        }
        networkingPeer.SendInstantiate(prefabName, position, rotation, group, array, data, false);
        return Optimization.Caching.Pool.NetworkInstantiate(prefabName, position, rotation, array[0], array, networkingPeer.currentLevelPrefix, group, data);
        //Hashtable evData = networkingPeer.SendInstantiate(prefabName, position, rotation, group, array, data, false);
        //return networkingPeer.DoInstantiate(evData, networkingPeer.mLocalActor, gameObject);
    }
public static GameObject InstantiateSceneObject(string prefabName, Vector3 position, Quaternion rotation, int group, object[] data)
    {
        if (!connected || (InstantiateInRoomOnly && !inRoom))
        {
            Debug.LogError(string.Concat(new object[]
            {
                "Failed to InstantiateSceneObject prefab: ",
                prefabName,
                ". Client should be in a room. Current connectionStateDetailed: ",
                connectionStateDetailed
            }));
            return null;
        }
        if (!IsMasterClient)
        {
            Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Client is not the MasterClient in this room.");
            return null;
        }
        GameObject gameObject = (GameObject)Optimization.Caching.CacheResources.Load(prefabName);
        if (gameObject == null)
        {
            Debug.LogError("Failed to InstantiateSceneObject prefab: " + prefabName + ". Verify the Prefab is in a Resources folder (and not in a subfolder)");
            return null;
        }
        if (gameObject.GetComponent<PhotonView>() == null)
        {
            Debug.LogError("Failed to InstantiateSceneObject prefab:" + prefabName + ". Prefab must have a PhotonView component.");
            return null;
        }
        Component[] photonViewsInChildren = gameObject.GetPhotonViewsInChildren();
        int[] array = AllocateSceneViewIDs(photonViewsInChildren.Length);
        if (array == null)
        {
            Debug.LogError(string.Concat(new object[]
            {
                "Failed to InstantiateSceneObject prefab: ",
                prefabName,
                ". No ViewIDs are free to use. Max is: ",
                MAX_VIEW_IDS
            }));
            return null;
        }
        Hashtable evData = networkingPeer.SendInstantiate(prefabName, position, rotation, group, array, data, true);
        return networkingPeer.DoInstantiate(evData, networkingPeer.mLocalActor, gameObject);
    }
public static bool JoinOrCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby typedLobby)
    {
        if (offlineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("JoinOrCreateRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            offlineModeRoom = new Room(roomName, roomOptions);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom, new object[0]);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom, new object[0]);
            return true;
        }
        else
        {
            if (networkingPeer.server != ServerConnection.MasterServer || !connectedAndReady)
            {
                Debug.LogError("JoinOrCreateRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
                return false;
            }
            if (string.IsNullOrEmpty(roomName))
            {
                Debug.LogError("JoinOrCreateRoom failed. A roomname is required. If you don't know one, how will you join?");
                return false;
            }
            return networkingPeer.OpJoinRoom(roomName, roomOptions, typedLobby, true);
        }
    }
public static bool JoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter)
    {
        if (offlineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("JoinRandomRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            offlineModeRoom = new Room("offline room", null);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom, new object[0]);
            return true;
        }
        else
        {
            if (networkingPeer.server != ServerConnection.MasterServer || !connectedAndReady)
            {
                Debug.LogError("JoinRandomRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
                return false;
            }
            Hashtable hashtable = new Hashtable();
            hashtable.MergeStringKeys(expectedCustomRoomProperties);
            if (expectedMaxPlayers > 0)
            {
                hashtable[byte.MaxValue] = expectedMaxPlayers;
            }
            return networkingPeer.OpJoinRandomRoom(hashtable, 0, null, matchingType, typedLobby, sqlLobbyFilter);
        }
    }
[Obsolete("Use overload with roomOptions and TypedLobby parameter.")]
    public static bool JoinRoom(string roomName, bool createIfNotExists)
    {
        if (connectionStateDetailed == PeerState.Joining || connectionStateDetailed == PeerState.Joined || connectionStateDetailed == PeerState.ConnectedToGameserver)
        {
            Debug.LogError("JoinRoom aborted: You can only join a room while not currently connected/connecting to a room.");
        }
        else if (room != null)
        {
            Debug.LogError("JoinRoom aborted: You are already in a room!");
        }
        else if (roomName == string.Empty)
        {
            Debug.LogError("JoinRoom aborted: You must specifiy a room name!");
        }
        else
        {
            if (offlineMode)
            {
                offlineModeRoom = new Room(roomName, null);
                NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom, new object[0]);
                return true;
            }
            return networkingPeer.OpJoinRoom(roomName, null, null, createIfNotExists);
        }
        return false;
    }
public static bool JoinRoom(string roomName)
    {
        if (offlineMode)
        {
            if (offlineModeRoom != null)
            {
                Debug.LogError("JoinRoom failed. In offline mode you still have to leave a room to enter another.");
                return false;
            }
            offlineModeRoom = new Room(roomName, null);
            NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom, new object[0]);
            return true;
        }
        else
        {
            if (networkingPeer.server != ServerConnection.MasterServer || !connectedAndReady)
            {
                Debug.LogError("JoinRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.");
                return false;
            }
            if (string.IsNullOrEmpty(roomName))
            {
                Debug.LogError("JoinRoom failed. A roomname is required. If you don't know one, how will you join?");
                return false;
            }
            return networkingPeer.OpJoinRoom(roomName, null, null, false);
        }
    }
public static void RemoveRPCs(PhotonPlayer targetPlayer)
    {
        if (!VerifyCreplacedeNetwork())
        {
            return;
        }
        if (!targetPlayer.IsLocal && !IsMasterClient)
        {
            Debug.LogError("Error; Only the MasterClient can call RemoveRPCs for other players.");
            return;
        }
        networkingPeer.OpCleanRpcBuffer(targetPlayer.ID);
    }
internal void InternalChangeLocalID(int newID)
    {
        if (!this.IsLocal)
        {
            Debug.LogError("ERROR You should never change PhotonPlayer IDs!");
            return;
        }
        var info = GetType().GetField(nameof(ID), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
        if (info != null)
        {
            info.SetValue(this, newID);
            InitializeCounters();
        }
        targetArray[0] = ID;
    }
public static GameObject NetworkInstantiate(string name, Vector3 position, Quaternion rotation, int instantioationId, int[] viewIDs, short prefix = 0, int group = 0, object[] data = null)
        {
            GameObject res = (name.StartsWith("RCreplacedet/") ? CacheResources.RCLoad(name) : CacheResources.Load(name)) as GameObject;
            if (res == null)
            {
                Debug.LogError($"Pool.NetworkInstantiate(): Cannot fint prefab with name "{name}".");
                return null;
            }
            PhotonView[] views = res.GetPhotonViewsInChildren();
            if (views.Length != viewIDs.Length)
            {
                throw new System.Exception($"Pool.NetworkInstantiate(): Error in Instantiation("{name}")! The resource's PhotonView count is not the same as in incoming data. {views.Length} != {viewIDs.Length}");
            }
            for (int i = 0; i < views.Length; i++)
            {
                views[i].viewID = viewIDs[i];
                views[i].prefix = prefix;
                views[i].instantiationId = instantioationId;
            }
            PhotonNetwork.networkingPeer.StoreInstantiationData(instantioationId, data);
            GameObject go = (GameObject)Object.Instantiate(res, position, rotation);
            for (int i = 0; i < views.Length; i++)
            {
                views[i].viewID = 0;
                views[i].prefix = -1;
                views[i].instantiationId = -1;
                views[i].prefixBackup = -1;
            }
            PhotonNetwork.networkingPeer.RemoveInstantiationData(instantioationId);
            if (PhotonNetwork.networkingPeer.instantiatedObjects.ContainsKey(instantioationId))
            {
                GameObject gameobj = PhotonNetwork.networkingPeer.instantiatedObjects[instantioationId];
                string str2 = string.Empty;
                if (gameobj != null)
                {
                    foreach (PhotonView view in gameobj.GetPhotonViewsInChildren())
                    {
                        if (view != null)
                        {
                            str2 = str2 + view.ToString() + ", ";
                        }
                    }
                }
                object[] args = new object[] { gameobj, instantioationId, PhotonNetwork.networkingPeer.instantiatedObjects.Count, go, str2, PhotonNetwork.lastUsedViewSubId, PhotonNetwork.lastUsedViewSubIdStatic, NetworkingPeer.photonViewList.Count };
                Debug.LogError(string.Format("DoInstantiate re-defines a GameObject. Destroying old entry! New: '{0}' (instantiationID: {1}) Old: {3}. PhotonViews on old: {4}. instantiatedObjects.Count: {2}. PhotonNetwork.lastUsedViewSubId: {5} PhotonNetwork.lastUsedViewSubIdStatic: {6} photonViewList.Count {7}.)", args));
                PhotonNetwork.networkingPeer.RemoveInstantiatedGO(go, true);
            }
            PhotonNetwork.networkingPeer.instantiatedObjects.Add(instantioationId, go);
            return go;
        }
public GameObject NetworkEnable(string name, Vector3 position, Quaternion rotation, int group = 0, object[] data = null, bool isSceneObject = false)
        {
            if (IN_GAME_MAIN_CAMERA.GameType != GameType.MultiPlayer)
            {
                Debug.LogError($"PoolObject.NetworkEnable(): Failed to NetworkEnable prefab, because GameType is not Multiplayer.");
                return null;
            }
            GameObject go = PickObject(name);
            PhotonView pv = go.GetComponent<PhotonView>();
            if (pv == null)
            {
                throw new System.Exception($"PoolObject.NetworkEnable(): Prefab "{name}" has not PhotonView component.");
            }
            PhotonView[] photonViews = go.GetPhotonViewsInChildren();
            int[] viewIDs = new int[photonViews.Length];
            for (int i = 0; i < viewIDs.Length; i++)
            {
                viewIDs[i] = PhotonNetwork.AllocateViewID(PhotonNetwork.player.ID);
            }
            PhotonNetwork.networkingPeer.SendInstantiate(name, position, rotation, group, viewIDs, data, isSceneObject);
            return NetworkInstantiate(name, position, rotation, viewIDs[0], viewIDs, (short)(PhotonNetwork.networkingPeer.currentLevelPrefix > 0 ? PhotonNetwork.networkingPeer.currentLevelPrefix : 0), group, data);

            #region Old version

            //for (int i = 0; i < photonViews.Length; i++)
            //{
            //    photonViews[i].viewID = viewIDs[i];
            //    photonViews[i].prefix = prefix;
            //    photonViews[i].instantiationId = instantiationId;
            //}
            //if (go.transform != null)
            //{
            //    go.transform.position = position;
            //    go.transform.rotation = rotation;
            //}
            //peer.StoreInstantiationData(instantiationId, data);
            //go.SetActive(true);
            //peer.RemoveInstantiationData(instantiationId);
            //if (peer.instantiatedObjects.ContainsKey(instantiationId))
            //{
            //    GameObject gameobj = peer.instantiatedObjects[instantiationId];
            //    string str2 = string.Empty;
            //    if (gameobj != null)
            //    {
            //        foreach (PhotonView view in gameobj.GetPhotonViewsInChildren())
            //        {
            //            if (view != null)
            //            {
            //                str2 = str2 + view.ToString() + ", ";
            //            }
            //        }
            //    }
            //    object[] args = new object[] { gameobj, instantiationId, peer.instantiatedObjects.Count, go, str2, PhotonNetwork.lastUsedViewSubId, PhotonNetwork.lastUsedViewSubIdStatic, NetworkingPeer.photonViewList.Count };
            //    Debug.LogError(string.Format("DoInstantiate re-defines a GameObject. Destroying old entry! New: '{0}' (instantiationID: {1}) Old: {3}. PhotonViews on old: {4}. instantiatedObjects.Count: {2}. PhotonNetwork.lastUsedViewSubId: {5} PhotonNetwork.lastUsedViewSubIdStatic: {6} photonViewList.Count {7}.)", args));
            //    peer.RemoveInstantiatedGO(go, true);
            //}
            //peer.instantiatedObjects.Add(instantiationId, go);
            //return go;

            #endregion Old version
        }
public GameObject NetworkInstantiate(string name, Vector3 position, Quaternion rotation, int instantioationId, int[] viewIDs, short prefix = 0, int group = 0, object[] data = null)
        {
            GameObject go = PickObject(name);
            if (!go.GetComponent<PhotonView>())
            {
                Debug.LogError($"PoolObject.NetworkInstantiate(): Prefab with name "{name}" has not PhotonView component!");
                return null;
            }
            PhotonView[] views = go.GetPhotonViewsInChildren();
            for (int i = 0; i < views.Length; i++)
            {
                views[i].didAwake = false;
                views[i].viewID = 0;
                views[i].prefix = prefix;
                views[i].instantiationId = instantioationId;
                views[i].instantiationData = data;
                views[i].didAwake = true;
                views[i].viewID = viewIDs[i];
            }
            if (go.transform)
            {
                go.transform.position = position;
                go.transform.rotation = rotation;
            }
            go.SetActive(true);
            PhotonNetwork.networkingPeer.RemoveInstantiationData(instantioationId);
            if (PhotonNetwork.networkingPeer.instantiatedObjects.ContainsKey(instantioationId))
            {
                GameObject gameobj = PhotonNetwork.networkingPeer.instantiatedObjects[instantioationId];
                string str2 = string.Empty;
                if (gameobj != null)
                {
                    foreach (PhotonView view in gameobj.GetPhotonViewsInChildren())
                    {
                        if (view != null)
                        {
                            str2 = str2 + view.ToString() + ", ";
                        }
                    }
                }
                object[] args = new object[] { gameobj, instantioationId, PhotonNetwork.networkingPeer.instantiatedObjects.Count, go, str2, PhotonNetwork.lastUsedViewSubId, PhotonNetwork.lastUsedViewSubIdStatic, NetworkingPeer.photonViewList.Count };
                Debug.LogError(string.Format("DoInstantiate re-defines a GameObject. Destroying old entry! New: '{0}' (instantiationID: {1}) Old: {3}. PhotonViews on old: {4}. instantiatedObjects.Count: {2}. PhotonNetwork.lastUsedViewSubId: {5} PhotonNetwork.lastUsedViewSubIdStatic: {6} photonViewList.Count {7}.)", args));
                PhotonNetwork.networkingPeer.RemoveInstantiatedGO(go, true);
            }
            PhotonNetwork.networkingPeer.instantiatedObjects.Add(instantioationId, go);
            return go;
        }
public static bool ConnectToBestCloudServer(string gameVersion)
    {
        if (PhotonServerSettings == null)
        {
            Debug.LogError("Can't connect: Loading settings failed. ServerSettings replacedet must be in any 'Resources' folder as: PhotonServerSettings");
            return false;
        }
        if (PhotonServerSettings.HostType == ServerSettings.HostingOption.OfflineMode)
        {
            return ConnectUsingSettings(gameVersion);
        }
        networkingPeer.IsInitialConnect = true;
        networkingPeer.SetApp(PhotonServerSettings.AppID, gameVersion);
        CloudRegionCode bestRegionCodeInPreferences = PhotonHandler.BestRegionCodeInPreferences;
        if (bestRegionCodeInPreferences != CloudRegionCode.none)
        {
            Debug.Log("Best region found in PlayerPrefs. Connecting to: " + bestRegionCodeInPreferences);
            return networkingPeer.ConnectToRegionMaster(bestRegionCodeInPreferences);
        }
        return networkingPeer.ConnectToNameServer();
    }
public void AddActiveNode(EffectNode node)
    {
        if (this.AvailableNodeCount == 0)
        {
            Debug.LogError("out index!");
        }
        if (this.AvailableENodes[node.Index] == null)
        {
            return;
        }
        this.ActiveENodes[node.Index] = node;
        this.AvailableENodes[node.Index] = null;
        this.AvailableNodeCount--;
    }
public void RemoveActiveNode(EffectNode node)
    {
        if (this.AvailableNodeCount == this.MaxENodes)
        {
            Debug.LogError("out index!");
        }
        if (this.ActiveENodes[node.Index] == null)
        {
            return;
        }
        this.ActiveENodes[node.Index] = null;
        this.AvailableENodes[node.Index] = node;
        this.AvailableNodeCount++;
    }
public void UpdateIndices()
    {
        if (!this.IndexDirty)
        {
            return;
        }
        VertexPool pool = this.Vertexsegment.Pool;
        if (this.Head != 99999 && this.Head != this.Tail)
        {
            int num = this.Head;
            int num2 = 0;
            for (; ; )
            {
                int num3 = num + 1;
                if (num3 == this.MaxElements)
                {
                    num3 = 0;
                }
                if (num3 * 2 >= 65536)
                {
                    Debug.LogError("Too many elements!");
                }
                int num4 = this.Vertexsegment.VertStart + num3 * 2;
                int num5 = this.Vertexsegment.VertStart + num * 2;
                int num6 = this.Vertexsegment.IndexStart + num2 * 6;
                pool.Indices[num6] = num5;
                pool.Indices[num6 + 1] = num5 + 1;
                pool.Indices[num6 + 2] = num4;
                pool.Indices[num6 + 3] = num5 + 1;
                pool.Indices[num6 + 4] = num4 + 1;
                pool.Indices[num6 + 5] = num4;
                if (num3 == this.Tail)
                {
                    break;
                }
                num = num3;
                num2++;
            }
            pool.IndiceChanged = true;
        }
        this.IndexDirty = false;
    }
public void UpdateVertices(Vector3 eyePos)
    {
        float num = 0f;
        float num2 = this.ElemLength * (float)(this.MaxElements - 2);
        if (this.Head != 99999 && this.Head != this.Tail)
        {
            int num3 = this.Head;
            int num4 = this.Head;
            for (; ; )
            {
                if (num4 == this.MaxElements)
                {
                    num4 = 0;
                }
                RibbonTrail.Element element = this.ElementArray[num4];
                if (num4 * 2 >= 65536)
                {
                    Debug.LogError("Too many elements!");
                }
                int num5 = this.Vertexsegment.VertStart + num4 * 2;
                int num6 = num4 + 1;
                if (num6 == this.MaxElements)
                {
                    num6 = 0;
                }
                Vector3 lhs;
                if (num4 == this.Head)
                {
                    lhs = this.ElementArray[num6].Position - element.Position;
                }
                else if (num4 == this.Tail)
                {
                    lhs = element.Position - this.ElementArray[num3].Position;
                }
                else
                {
                    lhs = this.ElementArray[num6].Position - this.ElementArray[num3].Position;
                }
                Vector3 rhs = eyePos - element.Position;
                Vector3 vector = Vector3.Cross(lhs, rhs);
                vector.Normalize();
                vector *= element.Width * 0.5f;
                Vector3 vector2 = element.Position - vector;
                Vector3 vector3 = element.Position + vector;
                VertexPool pool = this.Vertexsegment.Pool;
                float num7;
                if (this.StretchType == 0)
                {
                    num7 = num / num2 * Mathf.Abs(this.UVDimensions.y);
                }
                else
                {
                    num7 = num / num2 * Mathf.Abs(this.UVDimensions.x);
                }
                Vector2 zero = Vectors.v2zero;
                pool.Vertices[num5] = vector2;
                pool.Colors[num5] = this.Color;
                if (this.StretchType == 0)
                {
                    zero.x = this.LowerLeftUV.x + this.UVDimensions.x;
                    zero.y = this.LowerLeftUV.y - num7;
                }
                else
                {
                    zero.x = this.LowerLeftUV.x + num7;
                    zero.y = this.LowerLeftUV.y;
                }
                pool.UVs[num5] = zero;
                pool.Vertices[num5 + 1] = vector3;
                pool.Colors[num5 + 1] = this.Color;
                if (this.StretchType == 0)
                {
                    zero.x = this.LowerLeftUV.x;
                    zero.y = this.LowerLeftUV.y - num7;
                }
                else
                {
                    zero.x = this.LowerLeftUV.x + num7;
                    zero.y = this.LowerLeftUV.y - Mathf.Abs(this.UVDimensions.y);
                }
                pool.UVs[num5 + 1] = zero;
                if (num4 == this.Tail)
                {
                    break;
                }
                num3 = num4;
                num += (this.ElementArray[num6].Position - element.Position).magnitude;
                num4++;
            }
            this.Vertexsegment.Pool.UVChanged = true;
            this.Vertexsegment.Pool.VertChanged = true;
            this.Vertexsegment.Pool.ColorChanged = true;
        }
    }

See More Examples

Egor12

0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

1

18.01.2021, 14:23. Показов 40304. Ответов 16

Метки unity (Все метки)


Здраствуйте может кто то знает. Я создаю игру на движке unity и у меня ошибка CS0246 можете пожалуйста подсказать как её убрать?

AssetsSpawner.cs(8,12): error CS0246: The type or namespace name ‘Gameobject’ could not be found (are you missing a using directive or an assembly reference?)

вот такая ошибка.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
 
public class Spawner : MonoBehaviour
{
    public Gameobject[] Blocklines;
 
    public float speed;
    public float speedIncrease;
 
    // Update is called once per frame
    private void Update()
    {
        speed += spawner.speedIncrease * Time.deltaTime;
    }
 
    public void SpawnWave()
    {
        int rand = Random.Range(0, Blocklines.Length);
        Instantiate(Blocklines[rand], transform.postition, Quaternion.identity);
 
    }
 
 
 
 
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

18.01.2021, 14:23

Ответы с готовыми решениями:

Как убрать ошибку
Начал заниматься по книге Васильева А.Н. Программирование для начинающих на С#, первая программа…

Как убрать ошибку?
Привет всем. Загрузил сайт на opencart на хостинг. все работает. Но если пытаюсь зайти в админку…

Как убрать ошибку?
&quot;функция ord с параметрами указанных типов не найдена&quot;

Программа переводит два заданных числа из…

ошибка CS0246 в проекте как исправить?
При компиляции вылетает ошибка CS0246, как это исправить?

16

109 / 81 / 37

Регистрация: 13.01.2016

Сообщений: 395

18.01.2021, 16:50

2

Строка 8. GameObject. Вторая часть типа тоже с большой буквы



1



0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

18.01.2021, 16:58

 [ТС]

3

Огромное спасибо но теперь ошибка
AssetsSpawner.cs(15,18): error CS0103: The name ‘spawner’ does not exist in the current context



0



74 / 53 / 24

Регистрация: 19.10.2012

Сообщений: 212

18.01.2021, 18:10

4

speed += spawner.speedIncrease * Time.deltaTime; Убери spawner

speed += speedIncrease * Time.deltaTime;

Добавлено через 28 секунд
Используй IDE



1



250 / 186 / 68

Регистрация: 04.03.2019

Сообщений: 1,010

18.01.2021, 18:16

5

Цитата
Сообщение от Egor12
Посмотреть сообщение

spawner.speedIncreas

Spawner с большой буквы.
а еще лучше убрать как пишут выше



1



Egor12

0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

18.01.2021, 21:29

 [ТС]

6

Спасибо большое, но у меня появилась ещё одна ошибка

AssetsDownMover.cs(24,23): error CS1061: ‘Transform’ does not contain a definition for ‘postition’ and no accessible extension method ‘postition’ accepting a first argument of type ‘Transform’ could be found (are you missing a using directive or an assembly reference?)

что то я так понимаю с ‘Transform’ не так.

буду очень благодарен за помощь.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class Spawner : MonoBehaviour
{
    public GameObject[] Blocklines;
 
    public float speed;
    public float speedIncrease;
 
    // Update is called once per frame
    private void Update()
    {
        speed += speedIncrease * Time.deltaTime;
    }
 
    public void SpawnWave()
    {
        int rand = Random.Range(0, Blocklines.Length);
        Instantiate(Blocklines[rand], transform.postition, Quaternion.identity);
 
    }
 
 
 
 
}



0



74 / 53 / 24

Регистрация: 19.10.2012

Сообщений: 212

18.01.2021, 21:40

7

Во первых у тебя с верху написана ошибка. ее в переводчик.
Потом повторюсь используй IDE любой и настрой под Unity

Instantiate(Blocklines[rand], transform.postition, Quaternion.identity);
position

все красное ошибки твоего кода.
А так ты тут поселишься.

Миниатюры

Как убрать ошибку CS0246?
 



0



0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

18.01.2021, 22:02

 [ТС]

8

Спасибо мне 12 только учусь поэтому у меня столько ошибок )

2 первые ошибки я уже исправил. А там где postition его просто удалить ?

Я не настраивал visual studio под unity потому что не знал что это нужно делать, и не знаю как.



0



74 / 53 / 24

Регистрация: 19.10.2012

Сообщений: 212

18.01.2021, 22:26

9

Ну Youtube в помощь. Я тоже начал примерно в этом возрасте. Очень давно.



0



0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

18.01.2021, 22:51

 [ТС]

10

Спасибо понял. Так всё таки postition убрать из скрипта ?



0



74 / 53 / 24

Регистрация: 19.10.2012

Сообщений: 212

18.01.2021, 23:41

11

Лучший ответ Сообщение было отмечено Egor12 как решение

Решение

Цитата
Сообщение от Egor12
Посмотреть сообщение

Так всё таки postition убрать из скрипта ?

написано с ошибкой просто.
Правильно position а не posTition

Добавлено через 4 минуты
Выучи основы c# это не так много. Просто Азы. Потом основы Unity. Это неделя по вечерам. Может ты и не будешь далеко Гуру, но в таких мелочах не ошибешься. А юзать Unity будет интереснее. Мб и поймешь куда поступать. ) Удачи.



0



0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

19.01.2021, 10:59

 [ТС]

12

Хорошо огромное спасибо ))



0



0 / 0 / 0

Регистрация: 18.01.2021

Сообщений: 20

20.01.2021, 14:28

 [ТС]

13

Почему-то speedIncrease работает то есть скорость становиться больше со временем, а Spawner не работает он не спавнит BlockLines.



0



Eli_To4Ka

0 / 0 / 0

Регистрация: 23.11.2021

Сообщений: 1

23.11.2021, 12:37

14

Ночью сидел писал код, по примеру ютубера… у него все работает у меня нет… cs0246 ошибку выбивает.
Может ктото мне тыкнуть пальцем, где мои сонные глаза чегото не увидели?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
 
public class AchMenu : MonoBehaviour
{
    public int total_money;
    [SerializeField] Button firstAch;
    [SerializeFiled] bool isFirst;
    void Start()
    {
        total_money = PlayerPrefs.GetInt("total_money");
        isFirst = PlayerPrefs.GetInt("isFirst") == 1 ? true : false;
        if (total_money >= 10 && !isFirst)
        {
            firstAch.interactactable = true;
        }
        else
        {
            firstAch.interactactable = false;
        }
    }
 
    public void GetFirst()
    {
        int money = PlayerPrefs.GetInt("money");
        money += 10;
        PlayerPrefs.SetInt("money", money);
        isFirst = true;
        PlayerPrefs.SetInt("isFirst", isFirst ? 1 : 0);
    }
 
    public void ToMenu()
    {
        SceneManager.LoadScene(0);
    }
 
    void Update()
    {
 
    }
}



0



529 / 341 / 196

Регистрация: 18.10.2019

Сообщений: 1,152

23.11.2021, 14:13

15

Eli_To4Ka, interactactable. Правильно — interactable.
Строки 18 и 22.



0



Sovock

0 / 0 / 0

Регистрация: 06.02.2022

Сообщений: 1

06.02.2022, 16:13

16

Делал год из интеренета, всё сделал как на ролике, но появляется ошибка:

(AssetsscriptsMovePlayer.cs(49,20): error CS1061: ‘Rigidbody’ does not contain a definition for ‘AddForse’ and no accessible extension method ‘AddForse’ accepting a first argument of type ‘Rigidbody’ could be found (are you missing a using directive or an assembly reference?)

вот код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
 
public class MovePlayer : MonoBehaviour
{
    [Header("Скорость передвижения")]
    public float speed = 7f;
 
    [Header("Сила прыжка")]
    public float jumpPower = 200f;
 
    [Header("Земля под ногами???")]
    public bool ground;
 
    public Rigidbody rb;
 
 
 
    private void Update()
    {
        GetInput();
    }
 
    void GetInput()
    {
        if (Input.GetKey(KeyCode.W))
        {
            transform.localPosition += transform.forward * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.S))
        {
            transform.localPosition += -transform.forward * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.A))
        {
            transform.localPosition += -transform.right * speed * Time.deltaTime;
        }
        if (Input.GetKey(KeyCode.D))
        {
            transform.localPosition += transform.right * speed * Time.deltaTime;
        }
 
        if(Input.GetKeyDown(KeyCode.Space))
        {
            if(ground == true)
            {
                rb.AddForse(transform.up * jumpPower);
            }
        }
    }
 
    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.tag == "Ground")
        {
            ground = true;
        }    
    }
 
    private void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            ground = false;
        }
    }
}



0



529 / 341 / 196

Регистрация: 18.10.2019

Сообщений: 1,152

06.02.2022, 16:18

17

Sovock, метод правильно называется AddForce



0



Понравилась статья? Поделить с друзьями:
  • Error you cannot perform this operation unless you are root
  • Error you can find them in the drivers folder of flashtool
  • Error you are not using the aircoookie fork of the espasyncwebserver library
  • Error yaml scanner scannererror mapping values are not allowed here in docker compose yml
  • Error xvid codecs are not installed