Esempio n. 1
0
    /// <summary>
    /// performs a sphere check on a placement to look for objects
    /// matching 'vp_Layer.Mask.PhysicsBlockers'. upon finding any,
    /// re-executes itself for up to 'attempts' iterations
    /// </summary>
    public static bool AdjustPosition(vp_Placement p, float physicsRadius, int attempts = 1000)
    {
        attempts--;

        if (attempts > 0)
        {
            // TIP: this can be expanded upon to check for alternative object layers
            if (p.IsObstructed(physicsRadius))
            {
                // adjust the position with a random horizontal distance of up to 1 meter
                Vector3 newPos = Random.insideUnitSphere;
                p.Position.x += newPos.x;
                p.Position.z += newPos.z;
                AdjustPosition(p, physicsRadius, attempts);
            }
        }
        else
        {
            // ran out of attempts! set position to world origin
            Debug.LogWarning("(vp_Placement.AdjustPosition) Failed to find valid placement.");
            return(false);
        }

        return(true);
    }
Esempio n. 2
0
	/// <summary>
	/// performs a sphere check on a placement to look for objects
	/// matching 'vp_Layer.Mask.PhysicsBlockers'. upon finding any,
	/// re-executes itself for up to 'attempts' iterations
	/// </summary>
	public static bool AdjustPosition(vp_Placement p, float physicsRadius, int attempts = 1000)
	{

		attempts--;

		if (attempts > 0)
		{
			// TIP: this can be expanded upon to check for alternative object layers
			if (p.IsObstructed(physicsRadius))
			{

				// adjust the position with a random horizontal distance of up to 1 meter
				Vector3 newPos = Random.insideUnitSphere;
				p.Position.x += newPos.x;
				p.Position.z += newPos.z;
				AdjustPosition(p, physicsRadius, attempts);

			}
		}
		else
		{
			// ran out of attempts! set position to world origin
			Debug.LogWarning("(vp_Placement.AdjustPosition) Failed to find valid placement.");
			return false;
		}

		return true;

	}
    /// <summary>
    /// teleports all players to new positions as determined by
    /// their team spawnpoint settings
    /// </summary>
    public static void TransmitRespawnAll()
    {
        if (!PhotonNetwork.isMasterClient)
        {
            return;
        }

        foreach (vp_MPNetworkPlayer p in vp_MPNetworkPlayer.Players.Values)
        {
            if (p == null)
            {
                continue;
            }
            p.Player.Platform.Set(null);
            vp_Placement placement = null;
            if (vp_MPTeamManager.Exists)
            {
                placement = vp_MPPlayerSpawner.GetRandomPlacement(vp_MPTeamManager.GetTeamName(p.TeamNumber));
            }
            else
            {
                placement = vp_MPPlayerSpawner.GetRandomPlacement();
            }
            p.photonView.RPC("ReceivePlayerRespawn", PhotonTargets.All, placement.Position, placement.Rotation);
        }
    }
Esempio n. 4
0
    /// <summary>
    /// returns a placement confined to this spawnpoint's settings
    /// if 'physicsCheckRadius' is set collision checking will be
    /// performed against pre-existing objects
    /// </summary>
    public virtual vp_Placement GetPlacement(float physicsCheckRadius = 0.0f)
    {
        vp_Placement p = new vp_Placement();

        p.Position = transform.position;
        if (Radius > 0.0f)
        {
            Vector3 newPos = (Random.insideUnitSphere * Radius);
            p.Position.x += newPos.x;
            p.Position.z += newPos.z;
        }

        // stay clear of other physics blockers and snap to ground
        if (physicsCheckRadius != 0.0f)
        {
            if (!vp_Placement.AdjustPosition(p, physicsCheckRadius))
            {
                return(null);
            }
            vp_Placement.SnapToGround(p, physicsCheckRadius, GroundSnapThreshold);
        }

        // if spawnpoint is set to use random rotation - create one.
        // otherwise use the rotation of the spawnpoint
        if (RandomDirection)
        {
            p.Rotation = Quaternion.Euler(Vector3.up * Random.Range(0.0f, 360.0f));
        }
        else
        {
            p.Rotation = transform.rotation;
        }

        return(p);
    }
Esempio n. 5
0
	/// <summary>
	/// tries to snap a placement to the ground (meaning any object above
	/// or below it with an upwards-facing collider). a 'snapDistance' of
	/// '10' means that a unit spawning up to 10 meters above or below a
	/// collider will snap on top of it. NOTE: you may want to reduce the
	/// snap distance inside rooms with floors above it, and increase it
	/// in terrain with steep hills, respectively
	/// </summary>
	public static void SnapToGround(vp_Placement p, float radius, float snapDistance)
	{

		if (snapDistance == 0.0f)
			return;

		RaycastHit hitInfo;
		Physics.SphereCast(new Ray(p.Position + (Vector3.up * snapDistance), Vector3.down),
			radius, out hitInfo, snapDistance * 2.0f, vp_Layer.Mask.ExternalBlockers);
		if (hitInfo.collider != null)
			p.Position.y = hitInfo.point.y + 0.05f;	// spawn 5 centimeters above the surface just to be sure

	}
Esempio n. 6
0
    /// <summary>
    /// snaps the player to a placement decided by the specified spawnpoint, taking into
    /// account the spawnpoint's radius, ground snap and random rotation settings. if the
    /// player has a vp_Respawner component, its 'ObstructionRadius' setting will be used
    /// for obstruction checking. otherwise the obstruction radius will be 1 meter.
    /// </summary>
    public static void Teleport(vp_SpawnPoint spawnPoint)
    {
        if (spawnPoint == null)
        {
            return;
        }

        float obstructionRadius = ((m_Respawner != null) ? m_Respawner.ObstructionRadius : 1.0f);

        vp_Placement placement = spawnPoint.GetPlacement(obstructionRadius);

        Position = placement.Position;
        Rotation = placement.Rotation.eulerAngles;
        Stop();
    }
Esempio n. 7
0
    /// <summary>
    ///
    /// </summary>
    public void TransmitInitialSpawnInfo(PhotonPlayer player, int id, string name)
    {
        // allocate team number, player type and spawnpoint
        int          teamNumber     = 0;
        string       playerTypeName = null;
        vp_Placement placement      = null;

        if (vp_MPTeamManager.Exists)
        {
            teamNumber     = ((vp_MPTeamManager.Instance.Teams.Count <= 1) ? 0 : vp_MPTeamManager.Instance.GetSmallestTeam());
            playerTypeName = vp_MPTeamManager.Instance.GetTeamPlayerTypeName(teamNumber);
            placement      = vp_MPPlayerSpawner.GetRandomPlacement(vp_MPTeamManager.GetTeamName(teamNumber));
        }

        if (placement == null)
        {
            placement = vp_MPPlayerSpawner.GetRandomPlacement();
        }

        if (string.IsNullOrEmpty(playerTypeName))
        {
            vp_MPPlayerType playerType = vp_MPPlayerSpawner.GetDefaultPlayerType();
            if (playerType != null)
            {
                playerTypeName = playerType.name;
            }
            else
            {
                Debug.LogError("Error (" + this + ") Failed to assign PlayerType to player " + id.ToString() + ". Make sure player types are assigned in your vp_MPPlayerSpawner and vp_MPMaster components.");
            }
        }

        // spawn
        photonView.RPC("ReceiveInitialSpawnInfo", PhotonTargets.All, id, player, placement.Position, placement.Rotation, playerTypeName, teamNumber);

        // if JOINING player is the master, refresh the game clock since
        // there are no other players and the game needs to get started
        if (player.isMasterClient)
        {
            StartGame();
        }

        // send the entire game state to the joining player
        // NOTE: we don't need to send the game state of the joinee to all
        // the other players since it has just spawned in the form of a
        // fresh, clean copy of the remote player prefab in question
        TransmitGameState(player);
    }
Esempio n. 8
0
    /// <summary>
    /// tries to snap a placement to the ground (meaning any object above
    /// or below it with an upwards-facing collider). a 'snapDistance' of
    /// '10' means that a unit spawning up to 10 meters above or below a
    /// collider will snap on top of it. NOTE: you may want to reduce the
    /// snap distance inside rooms with floors above it, and increase it
    /// in terrain with steep hills, respectively
    /// </summary>
    public static void SnapToGround(vp_Placement p, float radius, float snapDistance)
    {
        if (snapDistance == 0.0f)
        {
            return;
        }

        RaycastHit hitInfo;

        Physics.SphereCast(new Ray(p.Position + (Vector3.up * snapDistance), Vector3.down),
                           radius, out hitInfo, snapDistance * 2.0f, vp_Layer.Mask.ExternalBlockers);
        if (hitInfo.collider != null)
        {
            p.Position.y = hitInfo.point.y + 0.05f;             // spawn 5 centimeters above the surface just to be sure
        }
    }
    /// <summary>
    /// this method responds to a 'TransmitRespawn' event raised by an object in the
    /// master scene, and sends out an RPC to trigger the respawn on remote machines.
    /// it is typically initiated by vp_DamageHandler.
    /// </summary>
    protected virtual void TransmitRespawn(Transform targetTransform, vp_Placement placement)
    {
        // --- respawning a PLAYER ---
        if (vp_MPNetworkPlayer.Get(targetTransform) != null)
        {
            vp_MPPlayerSpawner.TransmitPlayerRespawn(targetTransform, placement);
            return;
        }

        // --- respawning an OBJECT ---
        int viewID = vp_MPMaster.GetViewIDOfTransform(targetTransform);

        if (viewID > 0)
        {
            photonView.RPC("ReceiveObjectRespawn", PhotonTargets.Others, viewID, placement.Position, placement.Rotation);
        }
    }
Esempio n. 10
0
    /// <summary>
    /// gets a vp_Placement object based on the optional 'spawnPointTag'.
    /// if no tag is provided a random spawnspoint will be returned
    /// </summary>
    public static vp_Placement GetRandomPlacement(string spawnPointTag = null)
    {
        if (spawnPointTag == "NoTeam")
        {
            spawnPointTag = null;
        }

        //Debug.Log("spawnPointTag: " + spawnPointTag);

        vp_Placement placement = vp_SpawnPoint.GetRandomPlacement(0.5f, spawnPointTag);

        if (placement == null)
        {
            placement = new vp_Placement();
        }
        return(placement);
    }
Esempio n. 11
0
    /// <summary>
    /// respawns the network player of 'transform' at 'placement'
    /// </summary>
    public static void TransmitPlayerRespawn(Transform transform, vp_Placement placement)
    {
        if (!PhotonNetwork.isMasterClient)
        {
            return;
        }

        //UnityEngine.Debug.Log("respawning " + t.gameObject.name);

        vp_MPNetworkPlayer.RefreshPlayers();

        vp_MPNetworkPlayer player = vp_MPNetworkPlayer.Get(transform);

        if (player != null)
        {
            player.photonView.RPC("ReceivePlayerRespawn", PhotonTargets.All, placement.Position, placement.Rotation);
        }
    }
	/// <summary>
	/// this method responds to a 'TransmitRespawn' event raised by an object in the
	/// master scene, and sends out an RPC to trigger the respawn on remote machines.
	/// it is typically initiated by vp_DamageHandler.
	/// </summary>
	protected virtual void TransmitRespawn(Transform targetTransform, vp_Placement placement)
	{

		// --- respawning a PLAYER ---
		if (vp_MPNetworkPlayer.Get(targetTransform) != null)
		{
			vp_MPPlayerSpawner.TransmitPlayerRespawn(targetTransform, placement);
			return;
		}

		// --- respawning an OBJECT ---
		int viewID = vp_MPMaster.GetViewIDOfTransform(targetTransform);
		if (viewID > 0)
		{
			photonView.RPC("ReceiveObjectRespawn", PhotonTargets.Others, viewID, placement.Position, placement.Rotation);
		}
		
	}
    /// <summary>
    /// respawns the object if no other object is occupying the respawn area.
    /// otherwise reschedules respawning. NOTE: this method can only run in
    /// singleplayer and by a master in multiplayer. multiplayer _clients_
    /// will instead use the version of 'GetSpawnPoint' that takes a position
    /// and rotation (called directly by the master)
    /// </summary>
    public virtual void PickSpawnPoint()
    {
        // return if the object has been destroyed (for example
        // as a result of loading a new level while it was gone)
        if (this == null)
        {
            return;
        }

        // if mode is 'SamePosition' or the level has no spawnpoints, go to initial position
        if ((m_SpawnMode == SpawnMode.SamePosition) || (vp_SpawnPoint.SpawnPoints.Count < 1))
        {
            Placement.Position = m_InitialPosition;
            Placement.Rotation = m_InitialRotation;
            // if an object the size of 'RespawnCheckRadius' can't fit at
            // 'm_InitialPosition' ...
            if (Placement.IsObstructed(ObstructionRadius))
            {
                switch (m_ObstructionSolver)
                {
                case ObstructionSolver.Wait:
                    // ... just try again later!
                    vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
                    return;

                case ObstructionSolver.AdjustPlacement:
                    // try to adjust the position ...
                    if (!vp_Placement.AdjustPosition(Placement, ObstructionRadius))
                    {
                        // ... and only if we failed to adjust the position, try again later
                        vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
                        return;
                    }
                    break;
                }
            }
        }
        else
        {
            // placement will be calculated by the spawnpoint system.
            // NOTE: the obstruction solution logic becomes slightly
            // different with spawnpoints
            switch (m_ObstructionSolver)
            {
            case ObstructionSolver.Wait:
                // if an object the size of 'RespawnCheckRadius' can't fit at
                // this random spawnpoint ...
                Placement = vp_SpawnPoint.GetRandomPlacement(0.0f, SpawnPointTag);
                if (Placement == null)
                {
                    Placement   = new vp_Placement();
                    m_SpawnMode = SpawnMode.SamePosition;
                    PickSpawnPoint();
                }
                // NOTE: no 'snap to ground' in this mode since the snap logic
                // of 'GetRandomPlacement' is dependent on its input value
                if (Placement.IsObstructed(ObstructionRadius))
                {
                    // ... skip trying to adjust the position and try again later
                    vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
                    return;
                }
                break;

            case ObstructionSolver.AdjustPlacement:
                // if an object the size of 'RespawnCheckRadius' can't fit at
                // this random spawnpoint and we fail to adjust the position ...
                Placement = vp_SpawnPoint.GetRandomPlacement(ObstructionRadius, SpawnPointTag);
                if (Placement == null)
                {
                    // ... try again later
                    vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
                    return;
                }
                break;
            }
        }

        Respawn();
    }
Esempio n. 14
0
	/// <summary>
	/// respawns the object if no other object is occupying the respawn area.
	/// otherwise reschedules respawning. NOTE: this method can only run in
	/// singleplayer and by a master in multiplayer. multiplayer _clients_
	/// will instead use the version of 'GetSpawnPoint' that takes a position
	/// and rotation (called directly by the master)
	/// </summary>
	public virtual void PickSpawnPoint()
	{

		// return if the object has been destroyed (for example
		// as a result of loading a new level while it was gone)
		if (this == null)
			return;

		// if mode is 'SamePosition' or the level has no spawnpoints, go to initial position
		if ((m_SpawnMode == SpawnMode.SamePosition) || (vp_SpawnPoint.SpawnPoints.Count < 1))
		{

			Placement.Position = m_InitialPosition;
			Placement.Rotation = m_InitialRotation;
			// if an object the size of 'RespawnCheckRadius' can't fit at
			// 'm_InitialPosition' ...
			if (Placement.IsObstructed(ObstructionRadius))
			{
				switch (m_ObstructionSolver)
				{
					case ObstructionSolver.Wait:
						// ... just try again later!
						vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
						return;
					case ObstructionSolver.AdjustPlacement:
						// try to adjust the position ...
						if (!vp_Placement.AdjustPosition(Placement, ObstructionRadius))
						{
							// ... and only if we failed to adjust the position, try again later
							vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
							return;
						}
						break;
				}
			}
		}
		else
		{

			// placement will be calculated by the spawnpoint system.
			// NOTE: the obstruction solution logic becomes slightly
			// different with spawnpoints
			switch (m_ObstructionSolver)
			{
				case ObstructionSolver.Wait:
					// if an object the size of 'RespawnCheckRadius' can't fit at
					// this random spawnpoint ...
					Placement = vp_SpawnPoint.GetRandomPlacement(0.0f, SpawnPointTag);
					if (Placement == null)
					{
						Placement = new vp_Placement();
						m_SpawnMode = SpawnMode.SamePosition;
						PickSpawnPoint();
					}
					// NOTE: no 'snap to ground' in this mode since the snap logic
					// of 'GetRandomPlacement' is dependent on its input value
					if (Placement.IsObstructed(ObstructionRadius))
					{
						// ... skip trying to adjust the position and try again later
						vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
						return;
					}
					break;
				case ObstructionSolver.AdjustPlacement:
					// if an object the size of 'RespawnCheckRadius' can't fit at
					// this random spawnpoint and we fail to adjust the position ...
					Placement = vp_SpawnPoint.GetRandomPlacement(ObstructionRadius, SpawnPointTag);
					if (Placement == null)
					{
						// ... try again later
						vp_Timer.In(UnityEngine.Random.Range(MinRespawnTime, MaxRespawnTime), PickSpawnPoint, m_RespawnTimer);
						return;
					}
					break;
			}

		}

		Respawn();

	}
	/// <summary>
	/// gets a vp_Placement object based on the optional 'spawnPointTag'.
	/// if no tag is provided a random spawnspoint will be returned
	/// </summary>
	public static vp_Placement GetRandomPlacement(string spawnPointTag = null)
	{

		if (spawnPointTag == "NoTeam")
			spawnPointTag = null;

		//Debug.Log("spawnPointTag: " + spawnPointTag);

		vp_Placement placement = vp_SpawnPoint.GetRandomPlacement(0.5f, spawnPointTag);
		if (placement == null)
			placement = new vp_Placement();
		return placement;

	}
	/// <summary>
	/// respawns the network player of 'transform' at 'placement'
	/// </summary>
	public static void TransmitPlayerRespawn(Transform transform, vp_Placement placement)
	{
		
		if (!PhotonNetwork.isMasterClient)
			return;

		//UnityEngine.Debug.Log("respawning " + t.gameObject.name);

		vp_MPNetworkPlayer.RefreshPlayers();

		vp_MPNetworkPlayer player = vp_MPNetworkPlayer.Get(transform);
		if (player != null)
			player.photonView.RPC("ReceivePlayerRespawn", PhotonTargets.All, placement.Position, placement.Rotation);
		
	}
Esempio n. 17
0
    public static vp_Placement GetRandomPlacement(float physicsCheckRadius, string tag)
    {
        // abort if scene contains no spawnpoints
        if ((SpawnPoints == null) || (SpawnPoints.Count < 1))
        {
            return(null);
        }

        // fetch a random spawnpoint
        vp_SpawnPoint spawnPoint = null;

        if (string.IsNullOrEmpty(tag))
        {
            spawnPoint = GetRandomSpawnPoint();
        }
        else
        {
            spawnPoint = GetRandomSpawnPoint(tag);
            if (spawnPoint == null)
            {
                spawnPoint = GetRandomSpawnPoint();
                Debug.LogWarning("Warning (vp_SpawnPoint --> GetRandomPlacement) Could not find a spawnpoint tagged '" + tag + "'. Falling back to 'any random spawnpoint'.");
            }
        }

        // if no spawnpoint was found, revert to world origin
        if (spawnPoint == null)
        {
            Debug.LogError("Error (vp_SpawnPoint --> GetRandomPlacement) Could not find a spawnpoint" + (!string.IsNullOrEmpty(tag) ? (" tagged '" + tag + "'") : ".") + " Reverting to world origin.");
            return(null);
        }

        // found a spawnpoint! set placement position to that of
        // the spawnpoint and apply horizontal spawnpoint radius
        // offset (if any)
        vp_Placement p = new vp_Placement();

        p.Position = spawnPoint.transform.position;
        if (spawnPoint.Radius > 0.0f)
        {
            Vector3 newPos = (Random.insideUnitSphere * spawnPoint.Radius);
            p.Position.x += newPos.x;
            p.Position.z += newPos.z;
        }

        // stay clear of other physics blockers and snap to ground
        if (physicsCheckRadius != 0.0f)
        {
            if (!vp_Placement.AdjustPosition(p, physicsCheckRadius))
            {
                return(null);
            }
            vp_Placement.SnapToGround(p, physicsCheckRadius, spawnPoint.GroundSnapThreshold);
        }

        // if spawnpoint is set to use random rotation - create one.
        // otherwise use the rotation of the spawnpoint
        if (spawnPoint.RandomDirection)
        {
            p.Rotation = Quaternion.Euler(Vector3.up * Random.Range(0.0f, 360.0f));
        }
        else
        {
            p.Rotation = spawnPoint.transform.rotation;
        }

        return(p);
    }
Esempio n. 18
0
	public static vp_Placement GetRandomPlacement(float physicsCheckRadius, string tag)
	{

		// abort if scene contains no spawnpoints
		if((SpawnPoints == null) || (SpawnPoints.Count < 1))
			return null;

		// fetch a random spawnpoint
		vp_SpawnPoint spawnPoint = null;
		if (string.IsNullOrEmpty(tag))
			spawnPoint = GetRandomSpawnPoint();
		else
		{
			spawnPoint = GetRandomSpawnPoint(tag);
			if (spawnPoint == null)
			{
				spawnPoint = GetRandomSpawnPoint();
				Debug.LogWarning("Warning (vp_SpawnPoint --> GetRandomPlacement) Could not find a spawnpoint tagged '" + tag + "'. Falling back to 'any random spawnpoint'.");
			}
		}
		
		// if no spawnpoint was found, revert to world origin
		if (spawnPoint == null)
		{
			Debug.LogError("Error (vp_SpawnPoint --> GetRandomPlacement) Could not find a spawnpoint" + (!string.IsNullOrEmpty(tag) ? (" tagged '" + tag + "'") : ".") + " Reverting to world origin.");
			return null;
		}

		// found a spawnpoint! set placement position to that of
		// the spawnpoint and apply horizontal spawnpoint radius
		// offset (if any)
		vp_Placement p = new vp_Placement();
		p.Position = spawnPoint.transform.position;
		if(spawnPoint.Radius > 0.0f)
		{
			Vector3 newPos = (Random.insideUnitSphere * spawnPoint.Radius);
			p.Position.x += newPos.x;
			p.Position.z += newPos.z;
		}

		// stay clear of other physics blockers and snap to ground
		if (physicsCheckRadius != 0.0f)
		{
			if (!vp_Placement.AdjustPosition(p, physicsCheckRadius))
				return null;
			vp_Placement.SnapToGround(p, physicsCheckRadius, spawnPoint.GroundSnapThreshold);
		}

		// if spawnpoint is set to use random rotation - create one.
		// otherwise use the rotation of the spawnpoint
		if(spawnPoint.RandomDirection)
			p.Rotation = Quaternion.Euler(Vector3.up * Random.Range(0.0f, 360.0f));
		else
			p.Rotation = spawnPoint.transform.rotation;
	
		return p;

	}