Unity 3d Team Spawning with Photon 2 - unity3d

I have been stuck on this problem for a few months now. The problem being that I cannot properly instantiate my prefabs in the scene I want. I need the spawning to be one person on one team, and the rest on the other. But I'm not sure how to do that. What happens is that when I click the play button on my lobby menu, I get an error called "No cameras to display." I also noticed that the scene I want does load, but it doesn't switch to it because there are no cameras that are instantiated. I am using Photon 2. I am new to game development and your guys' help would be greatly appreciated! :)
I will post my code if that will help:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using TMPro;
using Photon.Realtime;
using System.Linq;
using System.IO;
public class Launcher : MonoBehaviourPunCallbacks
{
public static Launcher Instance;
[SerializeField] TMP_InputField roomNameInputField;
[SerializeField] TMP_Text errorText;
[SerializeField] TMP_Text RoomNameText;
[SerializeField] Transform RoomListBackground;
[SerializeField] Transform PlayerListBackground;
[SerializeField] GameObject roomListItem_pf;
[SerializeField] GameObject PlayerListItem_pf;
[SerializeField] GameObject startGameButton;
public PhotonView PV;
public int myTeam;
public GameObject myAvatar;
void Awake()
{
Instance = this;
}
void Start()
{
Debug.Log("Connecting to Master");
PhotonNetwork.ConnectUsingSettings();
}
public void Update()
{
PV = GetComponent<PhotonView>();
if (PV)
{
PV.RPC("RPC_GetTeam", RpcTarget.MasterClient);
}
if (myAvatar == null && myTeam != 0)
{
if (myTeam == 1)
{
if (PV.IsMine)
{
int spawnPicker = Random.Range(0, GameSetup.GS.spawnPointsTeamOne.Length);
myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Player"), GameSetup.GS.spawnPointsTeamOne[spawnPicker].position, GameSetup.GS.spawnPointsTeamOne[spawnPicker].rotation, 0);
}
}
if (myTeam == 2)
{
if (PV.IsMine)
{
int spawnPicker = Random.Range(0, GameSetup.GS.spawnPointsTeamTwo.Length);
myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Player"), GameSetup.GS.spawnPointsTeamTwo[spawnPicker].position, GameSetup.GS.spawnPointsTeamTwo[spawnPicker].rotation, 0);
}
}
}
}
public override void OnConnectedToMaster()
{
Debug.Log("Connected to Master");
PhotonNetwork.JoinLobby();
PhotonNetwork.AutomaticallySyncScene = true;
}
public override void OnJoinedLobby()
{
MenuManager.Instance.OpenMenu("title");
Debug.Log("Joined Lobby");
}
public void CreateRoom()
{
if (string.IsNullOrEmpty(roomNameInputField.text))
{
return;
}
PhotonNetwork.CreateRoom(roomNameInputField.text);
MenuManager.Instance.OpenMenu("loading");
}
public override void OnJoinedRoom()
{
MenuManager.Instance.OpenMenu("room");
RoomNameText.text = PhotonNetwork.CurrentRoom.Name;
Player[] players = PhotonNetwork.PlayerList;
for (int i = 0; i < players.Count(); i++)
{
Instantiate(PlayerListItem_pf, PlayerListBackground).GetComponent<PlayerListItem>().Setup(players);
}
startGameButton.SetActive(PhotonNetwork.IsMasterClient);
}
public override void OnMasterClientSwitched(Player newMasterClient)
{
startGameButton.SetActive(PhotonNetwork.IsMasterClient);
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
errorText.text = "Room Creation Failed: " + message;
MenuManager.Instance.OpenMenu("error");
}
public void LeaveRoom()
{
PhotonNetwork.LeaveRoom();
MenuManager.Instance.OpenMenu("loading");
}
public void JoinRoom(RoomInfo info)
{
PhotonNetwork.JoinRoom(info.Name);
MenuManager.Instance.OpenMenu("loading");
}
public override void OnLeftRoom()
{
MenuManager.Instance.OpenMenu("title");
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
foreach (Transform trans in RoomListBackground)
{
Destroy(trans.gameObject);
}
for (int i = 0; i < roomList.Count; i++)
{
Instantiate(roomListItem_pf, RoomListBackground).GetComponent<RoomListItem>().Setup(roomList);
}
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
Instantiate(PlayerListItem_pf, PlayerListBackground).GetComponent<PlayerListItem>().Setup(newPlayer);
}
[PunRPC]
public void RPC_GetTeam()
{
myTeam = GameSetup.GS.nextPlayersTeam;
GameSetup.GS.UpdateTeam();
PV.RPC("RPC_SentTeam", RpcTarget.OthersBuffered, myTeam);
}
[PunRPC]
public void RPC_SentTeam(int whichTeam)
{
myTeam = whichTeam;
}
}

Related

Unity Photon PUN2 Damage Indicator

I want to make a damage indicator for my online game, but there is an error in my code, can you check it?
Script 1
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class di_system : MonoBehaviour
{
[Header("References")]
[SerializeField] private DamageIndicator indicatorPrefab = null;
[SerializeField] private RectTransform holder = null;
[SerializeField] private Camera camera = null;
[SerializeField] private Transform player = null;
private Dictionary<Transform, DamageIndicator> Indicators = new Dictionary<Transform, DamageIndicator>();
#region Delegates
public static Action<Transform> CreateIndicator = delegate { };
public static Func<Transform, bool> CheckIfObjectInSight = null;
#endregion
private void OnEnable()
{
CreateIndicator += Create;
CheckIfObjectInSight += InSight;
}
private void OnDisable()
{
CreateIndicator -= Create;
CheckIfObjectInSight -= InSight;
}
void Create(Transform target)
{
if (Indicators.ContainsKey(target))
{
Indicators[target].Restart();
return;
}
DamageIndicator newIndicator = Instantiate(indicatorPrefab, holder);
newIndicator.Register(target, player, new Action(() => { Indicators.Remove(target); }));
Indicators.Add(target, newIndicator);
}
bool InSight(Transform t)
{
Vector3 screenPoint = camera.WorldToViewportPoint(t.position);
return screenPoint.z > 0 && screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
}
}
Script 2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
public class Health : MonoBehaviour
{
public float health;
public float maxHealth;
public float HealSpeed;
public Image healthBar;
float lerpSpeed;
public bool heal;
public PhotonView PV;
public Manager manager;
public bool dead;
public bool spawnShield;
public float spawnShieldTime;
public float SST;
public GameObject SSUI;
public GameObject SSUI2;
public Text healthText;
// Start is called before the first frame update
void Start()
{
manager = GameObject.FindWithTag("Scripts").GetComponent<Manager>();
spawnShield = true;
SST = spawnShieldTime;
}
// Update is called once per frame
void Update()
{
healthText.text = health.ToString("0");
if (Input.anyKey && spawnShield)
{
StartCoroutine(waitt());
}
if (spawnShield)
{
health = maxHealth;
SST -= 1f * Time.deltaTime;
SSUI.SetActive(true);
SSUI2.SetActive(true);
SSUI2.GetComponent<Text>().text = SST.ToString("0.0");
}
else
{
SSUI.SetActive(false);
SSUI2.SetActive(false);
}
if (SST <= 0)
{
PV.RPC("SpawnShieldOff", RpcTarget.All);
}
}
[PunRPC]
public void Damage(float damage)
{
Register();
health -= damage;
if (PV.IsMine)
{
if (health <= 0)
{
Die();
}
}
if (health <= 0)
{
dead = true;
}
}
public void Die()
{
manager.deaths++;
manager.cooldown();
manager.Alive = false;
PhotonNetwork.Destroy(gameObject);
}
[PunRPC]
public void SpawnShieldOff()
{
spawnShield = false;
}
void Register()
{
if (!di_system.CheckIfObjectInSight(this.transform))
{
di_system.CreateIndicator(this.transform);
}
}
}
I want to make damage indicators for my multiplayer game. Can you help me?
I've been trying to solve this problem for a long time but I couldn't find anything.
No errors in the code, but it shows the rotation of the damaged player instead of the rotation of the damaging player

how to spawn a prefab with filled object fields from scene

The game is working correctly and there arent any other issues apart from the fact that the public fields from the players scripts that are supposed to be filled with game objects from the scene arent filled and im not sure how to do that.
heres an example from one of the scripts: image
and heres what it should look like: image
the joystick area from the second image is from the scene, not an asset: image
here is the code im using:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePlayer : MonoBehaviour
{
public MovementJoystick movementJoystick;
public int playerSpeed;
private Rigidbody2D rb;
bool facingRight = true;
public Animator animator;
public float interval;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
playerSpeed = 7;
interval = 10;
}
// Update is called once per frame
void FixedUpdate()
{
if (movementJoystick.joystickVec.y != 0)
{
rb.velocity = new Vector2(movementJoystick.joystickVec.x * playerSpeed, movementJoystick.joystickVec.y * playerSpeed);
animator.SetFloat("speed", Mathf.Abs(movementJoystick.joystickVec.x));
}
else
{
rb.velocity = Vector2.zero;
animator.SetFloat("speed", Mathf.Abs(0));
}
if (movementJoystick.joystickVec.x < 0 && !facingRight)
{
Flip();
}
if (movementJoystick.joystickVec.x > 0 && facingRight)
{
Flip();
}
}
void Update()
{
if (playerSpeed == 14 && interval > 0)
{
interval -= Time.deltaTime;
}
else
{
playerSpeed = 7;
interval = 10;
}
}
void Flip()
{
transform.Rotate(0f, 180f, 0f);
facingRight = !facingRight;
}
public void SpeedControl(int newplayerSpeed)
{
playerSpeed = newplayerSpeed;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class MovementJoystick : MonoBehaviour
{
public GameObject joystick;
public GameObject joystickBG;
public Vector2 joystickVec;
private Vector2 joystickTouchPos;
private Vector2 joystickOriginalPos;
private float joystickRadius;
// Start is called before the first frame update
void Start()
{
joystickOriginalPos = joystickBG.transform.position;
joystickRadius = joystickBG.GetComponent<RectTransform>().sizeDelta.y / 2;
}
public void PointerDown()
{
joystick.transform.position = Input.mousePosition;
joystickBG.transform.position = Input.mousePosition;
joystickTouchPos = Input.mousePosition;
}
public void Drag(BaseEventData baseEventData)
{
PointerEventData pointerEventData = baseEventData as PointerEventData;
Vector2 dragPos = pointerEventData.position;
joystickVec = (dragPos - joystickTouchPos).normalized;
float joystickDist = Vector2.Distance(dragPos, joystickTouchPos);
if (joystickDist < joystickRadius)
{
joystick.transform.position = joystickTouchPos + joystickVec * joystickDist;
}
else
{
joystick.transform.position = joystickTouchPos + joystickVec * joystickRadius;
}
}
public void PointerUp()
{
joystickVec = Vector2.zero;
joystick.transform.position = joystickOriginalPos;
joystickBG.transform.position = joystickOriginalPos;
}
}
this is how to instantiate the player using photon servers (what i am using)
public GameObject playerToSpawn;
PhotonNetwork.Instantiate(playerToSpawn.name, spawnPoint.position, Quaternion.identity);
There are also 2 buttons i need you to fix: a Shoot button and a Hit button (those are the names). Here is the code for them:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShootButton : MonoBehaviour
{
//i made this script for the button incase you may
have
needed it
}
Here is the shooting script attached to the player:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Weapon : MonoBehaviour
{
public Transform firePoint;
public GameObject bulletPrefab;
public Button ShootButton;
void Start()
{
ShootButton.onClick.AddListener(ShootButtonTrue);
}
void ShootButtonTrue()
{
Shoot();
}
void Shoot()
{
Instantiate(bulletPrefab, firePoint.position,
firePoint.rotation);
}
}
Here is the hitting script attached to the Hit button
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HitButton : MonoBehaviour
{
}
And here is the Player Combat script using for hitting:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerCombat : MonoBehaviour
{
public Animator animator;
public Button AttackButton;
public Transform attackPoint;
public float attackRange = 0.5f;
public LayerMask enemyLayers;
void Start()
{
AttackButton.onClick.AddListener(AttackButtonTrue);
}
void AttackButtonTrue()
{
Attack();
}
void Attack()
{
animator.SetTrigger("Attack");
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPoint.position, attackRange, enemyLayers);
foreach(Collider2D enemy in hitEnemies)
{
Debug.Log("u hit someone :O");
enemy.GetComponent<Health>().TakeDamage(15);
}
}
void OnDrawGizmosSelected()
{
if (attackPoint == null)
return;
Gizmos.DrawWireSphere(attackPoint.position, attackRange);
}
}
if you need any other pieces of code just ask
thanks in advance, i will mark the answer as an answer if its a good answer
There are multiple ways to achieve this. For example, you can make your joystick singleton and assign that to the player upon spawn. If you have multiple joysticks in the scene, you can group them under the same parent object and make that parent singleton.
Assuming you only have one joystick in the scene, add this into your joystick class:
public static MovementJoystick Instance { get; private set; }
void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(this);
}
else
{
Instance = this;
}
}
In your player class, add this:
void OnEnable()
{
if( movemaneJoystick == null)
{
movementJoystick = MovementJoystick.Instance;
}
}

Swapping Two GameObjects on Keypress

When I press Space, the player and the dummy are supposed to swap places. This doesn't just happen once, it needs to happen everytime I press the Space bar so they can swap back and forth. However, sometimes it works and sometimes it doesn't. When it doesn't work, the dummy teleports to the player and then the player teleports inside of the dummy (as that is where its last position is). This just kind of pushes the player about.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerSwap : MonoBehaviour
{
public GameObject player;
public GameObject dummy;
public GameObject cameraAnchor;
public Transform playerLastPos;
public Transform dummyLastPos;
public bool haveSwapped;
public bool canSwap;
public float swapRadius;
public LayerMask dummyInRadius;
// Update is called once per frame
void Update()
{
canSwap = Physics.CheckSphere(player.transform.position, swapRadius, dummyInRadius);
SwapTransforms();
if (canSwap)
{
if (Input.GetKeyDown(KeyCode.Space))
{
haveSwapped = !haveSwapped;
Swapping();
}
}
else
{
Debug.Log("Can't Swap");
}
cameraAnchor.transform.position = player.transform.position;
}
public void SwapTransforms()
{
if (haveSwapped)
{
dummyLastPos.position = player.transform.position;
playerLastPos.position = dummy.transform.position;
}
else
{
dummyLastPos.position = dummy.transform.position;
playerLastPos.position = player.transform.position;
}
}
public void Swapping()
{
if (haveSwapped)
{
player.transform.position = dummyLastPos.position;
dummy.transform.position = playerLastPos.position;
}
else
{
player.transform.position = playerLastPos.position;
dummy.transform.position = dummyLastPos.position;
}
}
public void OnDrawGizmos()
{
Gizmos.color = Color.white;
Gizmos.DrawWireSphere(player.transform.position, swapRadius);
}
}
I've solved it. After cleaning up most of the code and realsing I had to turn off movement and the character controller on the player (Link:Unity Answers), I came up with this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerSwap : MonoBehaviour
{
public ThirdPersonMovement playerMove;
public GameObject player;
public GameObject dummy;
public GameObject cameraAnchor;
public Transform playerLastPos;
public Transform dummyLastPos;
public bool canSwap;
public float swapRadius;
public LayerMask dummyInRadius;
// Update is called once per frame
void Update()
{
canSwap = Physics.CheckSphere(player.transform.position, swapRadius, dummyInRadius);
if (canSwap)
{
if (Input.GetKeyDown(KeyCode.Space))
{
playerMove.canMove = false;
player.GetComponent<CharacterController>().enabled = false;
SetTransforms();
}
}
else
{
Debug.Log("Can't Swap");
}
cameraAnchor.transform.position = player.transform.position;
}
public void SetTransforms()
{
dummyLastPos.position = dummy.transform.position;
playerLastPos.position = player.transform.position;
Debug.Log("Set Transforms");
Swapping();
}
public void Swapping()
{
player.transform.position = dummyLastPos.position;
dummy.transform.position = playerLastPos.position;
dummy.transform.rotation = player.transform.rotation;
Debug.Log("Swap");
playerMove.canMove = true;
player.GetComponent<CharacterController>().enabled = true;
}
public void OnDrawGizmos()
{
Gizmos.color = Color.white;
Gizmos.DrawWireSphere(player.transform.position, swapRadius);
}
}

Minimum players to enter in a room PHOTON

I am doing a multiplayer game and I want to know how I can add a minimum number of players for a user to enter a room . Like to not be alone till one player is connected at least. What I should add to my script? I have this Room Options function but It doesn't work too add like Min players or something to it. (I expected if is MaxPlayers to exist MinPlayers too)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon;
using Photon.Pun;
using UnityEngine.UI;
using Photon.Realtime;
public class MPManager : MonoBehaviourPunCallbacks, IPunObservable
{
public PlayFabAuth auth;
public string GameVersion;
public Text connectState;
public GameObject[] DisableOnConnected;
public GameObject[] DisableOnJoinRoom;
public GameObject[] EnableOnConnected;
public GameObject[] EnableOnJoinRoom;
public LoadedPlayer loadPlayer;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
connectState.text = "Connection: " + PhotonNetwork.NetworkClientState;
}
public void ConnectToMaster()
{
// PhotonNetwork.connectionStateDetailed
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
PhotonNetwork.JoinLobby();
}
public override void OnJoinedLobby(){
foreach(GameObject disable in DisableOnConnected){
disable.SetActive(false);
}
foreach (GameObject enable in EnableOnConnected){
enable.SetActive(true);
}
}
public void CreateOrJoin()
{
PhotonNetwork.LeaveLobby();
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
RoomOptions rm = new RoomOptions
{
MaxPlayers = 3,
IsVisible = true
};
int rndID = Random.Range(0, 3000);
PhotonNetwork.CreateRoom("Default: " + rndID, rm, TypedLobby.Default);
}
public override void OnJoinedRoom()
{
foreach (GameObject disable in DisableOnJoinRoom)
{
disable.SetActive(false);
}
foreach (GameObject enable in EnableOnJoinRoom)
{
enable.SetActive(true);
}
Debug.Log(loadPlayer.currentPlayer.name);
GameObject player = PhotonNetwork.Instantiate(loadPlayer.currentPlayer.name , Vector3.zero, Quaternion.identity, 0);
}
public override void OnLeftRoom()
{
PhotonNetwork.LeaveRoom();
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
throw new System.NotImplementedException();
}
}
Thank you for choosing Photon!
You need to get the count of actors (PhotonNetwork.CurrentRoom.PlayerCount) when you join the room (OnJoinedRoom) or when another player joins the room (OnPlayerEnteredRoom). When the number of actors joined is enough for you, start the game logic, e.g. load scene, send a custom event etc.

Unity score text gets upadated inside unity editor but does not get updated in a real device

using UnityEngine;
using System.Collections;
public class Scoremanager : MonoBehaviour {
public static Scoremanager instance;
public int Score;
void Awake(){
if (instance == null) {
instance = this;
}
}
// Use this for initialization
void Start () {
Score = 0;
PlayerPrefs.SetInt ("Score", 0);
}
// Update is called once per frame
void Update () {
}
public void IncrementScore(){
Score++;
}
public void StopScore(){
PlayerPrefs.SetInt ("HighScore", Score);
if(PlayerPrefs.HasKey("HighScore")){
if (Score > PlayerPrefs.GetInt ("HighScore")) {
PlayerPrefs.SetInt ("HighScore", Score);
}
}
else{
PlayerPrefs.SetInt ("HighScore", Score);
}
}
The game runs well in the unity editor game view and the score text gets updated, but when i install the game in a real device,the score text does not get updated.Where am I going wrong guys?
public class ScoreManager : MonoBehaviour {
public static int Score{
get{
return PlayerPrefs.GetInt ("Score", 0);
}set{
PlayerPrefs.SetInt ("Score", value);
if (HighScore < value) {
PlayerPrefs.SetInt ("HighScore", value);
}
}
}
public static int HighScore{
get{
return PlayerPrefs.GetInt ("HighScore", 0);
}
}
void Start(){
Score = 0;
}
}
public class AnotherScript : MonoBehaviour {
void IncreaseScore(){
ScoreManager.Score++;
Debug.Log (ScoreManager.Score);
Debug.Log (ScoreManager.HighScore);
}
}
There is a way to do it and you can easily manage your game score.