Para esta lección tutorial, sobre cómo hacer un juego multijugador en Unity usando el complemento Photon 2 usaremos las funciones RPC que hemos aprendido para hacer un control básico de disparos en primera persona que se sincronizará a través de la red. Este tutorial le enseñará cómo usar la función RPC del complemento Photon 2 en otros escenarios. Después de esta lección, debe tener una mejor comprensión de la función RPC y lo que pueden hacer también cuando usarlos. También aprenderás cómo tomar cualquier máquina de juego y hacer que funcione en un juego multijugador.
Comenzaremos creando variables en nuestro script de configuración de Avatar, el primero será la salud del jugador y el siguiente será el daño del jugador. Luego crearemos un nuevo script de C# llamado Avatar Combat. En este script, crearemos algunas variables nuevas. Luego inicializaremos estas variables. Luego crearemos una función de disparo y usaremos Raycast para hacerlo. Primero queremos verificar la entrada del jugador y luego crearemos nuestro Raycast. Si el Raycast golpeó a otro jugador, entonces queremos eliminar la salud de ese jugador. Luego guardaremos nuestro script C# y volveremos a Unity.
En Unity, crearemos y agregaremos una nueva cámara a nuestro objeto avatar de jugador. Luego necesitamos adjuntar nuestros nuevos scripts a sus respectivos objetos y establecer las variables.
Luego volveremos a nuestro script de combate Avatar y convertiremos este script en un script que funcionará en toda la red. Haremos esto creando una función RPC que sincronizará la salud del jugador a través de la red cuando el jugador haya recibido un disparo.
Si seguiste el video, entonces ahora deberías tener un controlador FPS básico que funcione y que conecte la salud del jugador cuando te disparen.
AvatarSetup
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AvatarSetup : MonoBehaviour
{
private PhotonView PV;
public GameObject myCharacter;
public int characterValue;
// Start is called before the first frame update
void Start()
{
PV = GetComponent<PhotonView>();
if (PV.IsMine)
{
PV.RPC("RPC_AddCharacter", RpcTarget.AllBuffered, PlayerInfo.PI.mySelectedCharacter);
}
}
[PunRPC]
void RPC_AddCharacter(int whichCharacter)
{
characterValue = whichCharacter;
myCharacter = Instantiate(PlayerInfo.PI.allCharacters[whichCharacter], transform.position, transform.rotation, transform);
}
}
MenuController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MenuController : MonoBehaviour
{
public void OnClickCharacterPick(int whichCharacter)
{
if (PlayerInfo.PI != null)
{
PlayerInfo.PI.mySelectedCharacter = whichCharacter;
PlayerPrefs.SetInt("MyCharacter", whichCharacter);
}
}
}
PlayerInfo
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerInfo : MonoBehaviour
{
public static PlayerInfo PI;
public int mySelectedCharacter;
public GameObject[] allCharacters;
private void OnEnable()
{
if (PlayerInfo.PI == null)
{
PlayerInfo.PI = this;
}
else
{
if (PlayerInfo.PI != this)
{
Destroy(PlayerInfo.PI.gameObject);
PlayerInfo.PI = this;
}
}
DontDestroyOnLoad(this.gameObject);
}
// Start is called before the first frame update
void Start()
{
if (PlayerPrefs.HasKey("MyCharacter"))
{
mySelectedCharacter = PlayerPrefs.GetInt("MyCharacter");
}
else
{
mySelectedCharacter = 0;
PlayerPrefs.SetInt("MyCharacter",mySelectedCharacter);
}
}
}
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Aquí está la próxima lección sobre cómo hacer un juego multijugador en Unity usando el complemento Photon 2. Para esta lección, nos centraremos en el movimiento del jugador y sincronizaremos la transformación a través de la red utilizando la vista de transformación de Photon. Es muy importante poder sincronizar el movimiento de los jugadores a través de la red porque, sin hacerlo, los jugadores podrán verse en diferentes lugares de lo que realmente están. También es importante asegurarse de que cada jugador solo pueda controlar sus propios avatares.
Lo primero que debemos hacer es abrir nuestro prefab Avatar de Photon Player. En este prefabricado, agregaremos la Vista de transformación de Photon para que nuestro avatar jugador pueda sincronizar su movimiento. Luego, necesitaremos crear un nuevo script de C # para configurar los controles para el movimiento del objeto Avatar. Con este script C# abierto, lo primero que haremos es crear algunas variables nuevas. Luego inicializaremos todas nuestras variables. A medida que creamos las funciones de movimiento, primero debemos verificar la entrada del jugador. Según la entrada del jugador, moveremos el objeto avatar del jugador. Cuando llamamos a esta función de movimiento es la función de actualización, utilizaremos la variable Vista de Photon para verificar si este objeto es propiedad del jugador local. Esto es para asegurarse de que solo el jugador local pueda controlar su avatar y no los avatares de otras personas. Luego guardaremos nuestro script y volveremos a Unity 3D.
Si sigue el vídeo, ahora debería poder construir su proyecto. En la escena multijugador, ahora deberías poder controlar el movimiento de tu avatar de jugador local.
PlayerMovement
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private PhotonView PV;
private CharacterController myCC;
public float movementSpeed;
public float rotationSpeed;
// Start is called before the first frame update
void Start()
{
PV = GetComponent<PhotonView>();
myCC = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if(PV.IsMine && PhotonNetwork.IsConnected)
{
BasicMovement();
BasicRotation();
}
}
void BasicMovement()
{
if(Input.GetKey(KeyCode.W))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
}
void BasicRotation()
{
float mouseX = Input.GetAxis("Mouse X") * Time.deltaTime * rotationSpeed;
transform.Rotate(new Vector3(0, mouseX, 0));
}
}
PhotonLobby
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
public class PhotonLobby : MonoBehaviourPunCallbacks
{
// Start is called before the first frame update
public static PhotonLobby lobby;
public GameObject battleButton;
RoomInfo[] room;
public GameObject cancelButtom;
private void Awake()
{
lobby = this;
}
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Debug.Log("the conection is stablished");
PhotonNetwork.AutomaticallySyncScene = true;
battleButton.SetActive(true);
}
public void OnBattleButtonClicked()
{
Debug.Log("llego aca paso algo en la el battle button click");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
//base.OnJoinRandomFailed(returnCode, message);
Debug.Log("failed joining the room");
CreateRoom();
}
void CreateRoom()
{
Debug.Log("llego a CreateRoom");
int randomRoomName = Random.Range(0, 10000);
RoomOptions roomOps = new RoomOptions()
{
IsVisible = true,
IsOpen = true,
MaxPlayers = (byte)MultiplayerSettings.multiplayerSettings.maxPlayers
};
PhotonNetwork.CreateRoom("Room" + randomRoomName, roomOps, null);
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
//base.OnCreateRoomFailed(returnCode, message);
Debug.Log("failed creating the room");
CreateRoom();
}
public void OnCancelButtonCliked()
{
Debug.Log("Llego OnCancelButtonCliked");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.LeaveRoom();
}
}
PhotonPlayer
using Photon.Pun;
using System.IO;
using UnityEngine;
public class PhotonPlayer : MonoBehaviour
{
// Start is called before the first frame update
private PhotonView PV;
public GameObject myAvatar;
public GameObject myMainCamera;
void Start()
{
PV = GetComponent<PhotonView>();
int spawnPicker = Random.Range(0, GameSetUp.GS.spawnPoints.Length);
if (PV.IsMine)
{
myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PlayerAvatar"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);
/*myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Character 1"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);*/
}
}
}
PhotonRoom
using Photon.Pun;
using Photon.Realtime;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PhotonRoom : MonoBehaviourPunCallbacks, IInRoomCallbacks
{
// Start is called before the first frame update
public static PhotonRoom room;
private PhotonView PV;
public bool IsGameLoaded;
public int currentScene;
private Photon.Realtime.Player[] photonPlayers;
public int playersInRoom;
public int myNumberInRoom;
public int playerInGame;
private bool readyToCount;
private bool readyToStart;
public float startingTime;
private float lessThanMaxPlayer;
private float atMaxPlayer;
private float timeToStart;
private void Awake()
{
if(PhotonRoom.room == null)
{
PhotonRoom.room = this;
}
else
{
if(PhotonRoom.room != this)
{
Destroy(PhotonRoom.room.gameObject);
PhotonRoom.room = this;
}
}
DontDestroyOnLoad(this.gameObject);
}
public override void OnEnable()
{
base.OnEnable();
PhotonNetwork.AddCallbackTarget(this);
SceneManager.sceneLoaded += OnSceneFinishedLoading;
}
public override void OnDisable()
{
base.OnDisable();
PhotonNetwork.RemoveCallbackTarget(this);
SceneManager.sceneLoaded -= OnSceneFinishedLoading;
}
void Start()
{
PV = GetComponent<PhotonView>();
readyToCount = false;
readyToStart = false;
lessThanMaxPlayer = startingTime;
atMaxPlayer = 6;
timeToStart = startingTime;
}
// Update is called once per frame
void Update()
{
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
if(playersInRoom == 1)
{
RestartTimer();
}
if (!IsGameLoaded)
{
if (readyToStart)
{
atMaxPlayer -= Time.deltaTime;
lessThanMaxPlayer = atMaxPlayer;
timeToStart = atMaxPlayer;
}
else if (readyToCount)
{
lessThanMaxPlayer -= Time.deltaTime;
timeToStart = lessThanMaxPlayer;
}
Debug.Log("Displayer time to start to the players " + timeToStart );
if (timeToStart <=0)
{
StartGame();
}
}
}
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
Debug.Log("Se Unio a OnJoinedRoom");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom = photonPlayers.Length;
myNumberInRoom = playersInRoom;
PhotonNetwork.NickName = myNumberInRoom.ToString();
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible ("+playersInRoom+":"+MultiplayerSettings.multiplayerSettings.maxPlayers+")");
if(playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
else
{
StartGame();
}
}
public override void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer)
{
base.OnPlayerEnteredRoom(newPlayer);
Debug.Log("A new player has joined the room");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom++;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible (" + playersInRoom + ":" + MultiplayerSettings.multiplayerSettings.maxPlayers + ")");
if (playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (!PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
}
void StartGame()
{
IsGameLoaded = true;
if (!PhotonNetwork.IsMasterClient)
return;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
PhotonNetwork.CurrentRoom.IsOpen = false;
}
PhotonNetwork.LoadLevel(MultiplayerSettings.multiplayerSettings.multiplayerScene);
}
void RestartTimer()
{
lessThanMaxPlayer = startingTime;
timeToStart = startingTime;
atMaxPlayer = 6;
readyToCount = false;
readyToStart = false;
}
void OnSceneFinishedLoading(Scene scene, LoadSceneMode mode)
{
currentScene = scene.buildIndex;
if (currentScene ==MultiplayerSettings.multiplayerSettings.multiplayerScene)
{
IsGameLoaded = true;
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
PV.RPC("RPC_loadedGameScene", RpcTarget.MasterClient);
}
else
{
RPC_CreatePlayer();
}
}
}
[PunRPC]
private void RPC_LoadedGameScene()
{
playerInGame++;
if (playerInGame == PhotonNetwork.PlayerList.Length)
{
PV.RPC("RPC_CreatePlayer",RpcTarget.All);
}
}
[PunRPC]
private void RPC_CreatePlayer()
{
PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PhotonNetworkPlayer"), transform.position, Quaternion
.identity, 0);
}
}
GameSetUp
using UnityEngine;
public class GameSetUp : MonoBehaviour
{
// Start is called before the first frame update
public static GameSetUp GS;
public Transform[] spawnPoints;
private void OnEnable()
{
if (GameSetUp.GS == null)
{
GameSetUp.GS = this;
}
}
}
MultiplayerSettings
using UnityEngine;
public class MultiplayerSettings : MonoBehaviour
{
// Start is called before the first frame update
public static MultiplayerSettings multiplayerSettings;
public bool delayStart;
public int maxPlayers;
public int menuScene;
public int multiplayerScene;
private void Awake()
{
if(MultiplayerSettings.multiplayerSettings == null)
{
MultiplayerSettings.multiplayerSettings = this;
}
else
{
if(MultiplayerSettings.multiplayerSettings != this)
{
Destroy(this.gameObject);
}
}
DontDestroyOnLoad(this.gameObject);
}
}
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Bienvenido a esta nueva serie de tutoriales sobre la creación de videojuegos multijugador en Unity usando el complemento Photon 2 PUN. Para esta lección, le mostraremos cómo descargar, instalar y configurar el complemento Photon 2 en sus proyectos de Unity. Antes de seguir con cualquiera de las otras lecciones de esta serie de tutoriales, debe completar este video. Proporcionaremos los complementos descargables para todos los demás videos de esta serie, pero estos complementos no incluirán el complemento Photon original. Debe obtenerlo del sitio web oficial de Photon.
Lo primero que deberá hacer en esta lección es crear una cuenta de Photon. Una vez que haya registrado una cuenta, deberá crear un nuevo proyecto de aplicación Photon. Luego deberás completar información sobre tu juego multijugador y luego harás clic en crear. Después de crear una nueva aplicación, deberá copiar el ID de aplicación para más adelante.
De vuelta en Unity, deberá ir a Unity Asset Store y buscar el complemento gratuito PUN 2. Deberá descargar e instalar este complemento en su proyecto. Después de importar este complemento, aparecerá una nueva ventana. Este es el asistente de PUN y debe pegar su AppID de proyecto en esta ventana y luego hará clic en configurar proyecto. Lo siguiente que haremos es establecer nuestra primera conexión con el servidor maestro Photon. Para hacer esto, necesitaremos crear un nuevo script. En este nuevo script, lo único que haremos para este tutorial es inicializar la conexión de red.
PlayerMovement
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private PhotonView PV;
private CharacterController myCC;
public float movementSpeed;
public float rotationSpeed;
// Start is called before the first frame update
void Start()
{
PV = GetComponent<PhotonView>();
myCC = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if(PV.IsMine && PhotonNetwork.IsConnected)
{
BasicMovement();
BasicRotation();
}
}
void BasicMovement()
{
if(Input.GetKey(KeyCode.W))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
}
void BasicRotation()
{
float mouseX = Input.GetAxis("Mouse X") * Time.deltaTime * rotationSpeed;
transform.Rotate(new Vector3(0, mouseX, 0));
}
}
PhotonLobby
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
public class PhotonLobby : MonoBehaviourPunCallbacks
{
// Start is called before the first frame update
public static PhotonLobby lobby;
public GameObject battleButton;
RoomInfo[] room;
public GameObject cancelButtom;
private void Awake()
{
lobby = this;
}
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Debug.Log("the conection is stablished");
PhotonNetwork.AutomaticallySyncScene = true;
battleButton.SetActive(true);
}
public void OnBattleButtonClicked()
{
Debug.Log("llego aca paso algo en la el battle button click");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
//base.OnJoinRandomFailed(returnCode, message);
Debug.Log("failed joining the room");
CreateRoom();
}
void CreateRoom()
{
Debug.Log("llego a CreateRoom");
int randomRoomName = Random.Range(0, 10000);
RoomOptions roomOps = new RoomOptions()
{
IsVisible = true,
IsOpen = true,
MaxPlayers = (byte)MultiplayerSettings.multiplayerSettings.maxPlayers
};
PhotonNetwork.CreateRoom("Room" + randomRoomName, roomOps, null);
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
//base.OnCreateRoomFailed(returnCode, message);
Debug.Log("failed creating the room");
CreateRoom();
}
public void OnCancelButtonCliked()
{
Debug.Log("Llego OnCancelButtonCliked");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.LeaveRoom();
}
}
PhotonPlayer
using Photon.Pun;
using System.IO;
using UnityEngine;
public class PhotonPlayer : MonoBehaviour
{
// Start is called before the first frame update
private PhotonView PV;
public GameObject myAvatar;
public GameObject myMainCamera;
void Start()
{
PV = GetComponent<PhotonView>();
int spawnPicker = Random.Range(0, GameSetUp.GS.spawnPoints.Length);
if (PV.IsMine)
{
myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PlayerAvatar"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);
/*myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Character 1"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);*/
}
}
}
PhotonRoom
using Photon.Pun;
using Photon.Realtime;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PhotonRoom : MonoBehaviourPunCallbacks, IInRoomCallbacks
{
// Start is called before the first frame update
public static PhotonRoom room;
private PhotonView PV;
public bool IsGameLoaded;
public int currentScene;
private Photon.Realtime.Player[] photonPlayers;
public int playersInRoom;
public int myNumberInRoom;
public int playerInGame;
private bool readyToCount;
private bool readyToStart;
public float startingTime;
private float lessThanMaxPlayer;
private float atMaxPlayer;
private float timeToStart;
private void Awake()
{
if(PhotonRoom.room == null)
{
PhotonRoom.room = this;
}
else
{
if(PhotonRoom.room != this)
{
Destroy(PhotonRoom.room.gameObject);
PhotonRoom.room = this;
}
}
DontDestroyOnLoad(this.gameObject);
}
public override void OnEnable()
{
base.OnEnable();
PhotonNetwork.AddCallbackTarget(this);
SceneManager.sceneLoaded += OnSceneFinishedLoading;
}
public override void OnDisable()
{
base.OnDisable();
PhotonNetwork.RemoveCallbackTarget(this);
SceneManager.sceneLoaded -= OnSceneFinishedLoading;
}
void Start()
{
PV = GetComponent<PhotonView>();
readyToCount = false;
readyToStart = false;
lessThanMaxPlayer = startingTime;
atMaxPlayer = 6;
timeToStart = startingTime;
}
// Update is called once per frame
void Update()
{
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
if(playersInRoom == 1)
{
RestartTimer();
}
if (!IsGameLoaded)
{
if (readyToStart)
{
atMaxPlayer -= Time.deltaTime;
lessThanMaxPlayer = atMaxPlayer;
timeToStart = atMaxPlayer;
}
else if (readyToCount)
{
lessThanMaxPlayer -= Time.deltaTime;
timeToStart = lessThanMaxPlayer;
}
Debug.Log("Displayer time to start to the players " + timeToStart );
if (timeToStart <=0)
{
StartGame();
}
}
}
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
Debug.Log("Se Unio a OnJoinedRoom");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom = photonPlayers.Length;
myNumberInRoom = playersInRoom;
PhotonNetwork.NickName = myNumberInRoom.ToString();
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible ("+playersInRoom+":"+MultiplayerSettings.multiplayerSettings.maxPlayers+")");
if(playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
else
{
StartGame();
}
}
public override void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer)
{
base.OnPlayerEnteredRoom(newPlayer);
Debug.Log("A new player has joined the room");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom++;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible (" + playersInRoom + ":" + MultiplayerSettings.multiplayerSettings.maxPlayers + ")");
if (playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (!PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
}
void StartGame()
{
IsGameLoaded = true;
if (!PhotonNetwork.IsMasterClient)
return;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
PhotonNetwork.CurrentRoom.IsOpen = false;
}
PhotonNetwork.LoadLevel(MultiplayerSettings.multiplayerSettings.multiplayerScene);
}
void RestartTimer()
{
lessThanMaxPlayer = startingTime;
timeToStart = startingTime;
atMaxPlayer = 6;
readyToCount = false;
readyToStart = false;
}
void OnSceneFinishedLoading(Scene scene, LoadSceneMode mode)
{
currentScene = scene.buildIndex;
if (currentScene ==MultiplayerSettings.multiplayerSettings.multiplayerScene)
{
IsGameLoaded = true;
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
PV.RPC("RPC_loadedGameScene", RpcTarget.MasterClient);
}
else
{
RPC_CreatePlayer();
}
}
}
[PunRPC]
private void RPC_LoadedGameScene()
{
playerInGame++;
if (playerInGame == PhotonNetwork.PlayerList.Length)
{
PV.RPC("RPC_CreatePlayer",RpcTarget.All);
}
}
[PunRPC]
private void RPC_CreatePlayer()
{
PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PhotonNetworkPlayer"), transform.position, Quaternion
.identity, 0);
}
}
GameSetUp
using UnityEngine;
public class GameSetUp : MonoBehaviour
{
// Start is called before the first frame update
public static GameSetUp GS;
public Transform[] spawnPoints;
private void OnEnable()
{
if (GameSetUp.GS == null)
{
GameSetUp.GS = this;
}
}
}
MultiplayerSettings
using UnityEngine;
public class MultiplayerSettings : MonoBehaviour
{
// Start is called before the first frame update
public static MultiplayerSettings multiplayerSettings;
public bool delayStart;
public int maxPlayers;
public int menuScene;
public int multiplayerScene;
private void Awake()
{
if(MultiplayerSettings.multiplayerSettings == null)
{
MultiplayerSettings.multiplayerSettings = this;
}
else
{
if(MultiplayerSettings.multiplayerSettings != this)
{
Destroy(this.gameObject);
}
}
DontDestroyOnLoad(this.gameObject);
}
}
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
En ésta oportunidad comenzamos con la configuración inicial y la realización de la lógica de creación de salas unión a salas, y ubicación de objeto player en la escena en ésta serie abarcaremos la creación de nuestro videojuego TPS en la modalidad Multijugador con Photon 2 en Unity 3D. La implementación multijugador es independiente del juego la haremos así para que puedas utilizarla en cualquier otro proyecto que requieras.
La baja latencia es un requisito esencial en los juegos multijugador en tiempo real. Por esta razón, Photon Cloud está alojado en todas las principales regiones del mundo para brindar a sus jugadores una latencia mínima.
Los juegos que dependen de una latencia baja, como los tipos de juegos FPS o RTS, conectan a los jugadores con la región más cercana. Los juegos que pueden manejar una mayor latencia, como los juegos por turnos, pueden conectar a todos los jugadores a la misma región.
PlayerMovement
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
private PhotonView PV;
private CharacterController myCC;
public float movementSpeed;
public float rotationSpeed;
// Start is called before the first frame update
void Start()
{
PV = GetComponent<PhotonView>();
myCC = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if(PV.IsMine && PhotonNetwork.IsConnected)
{
BasicMovement();
BasicRotation();
}
}
void BasicMovement()
{
if(Input.GetKey(KeyCode.W))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
myCC.Move(transform.forward * Time.deltaTime * movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
myCC.Move(transform.right * Time.deltaTime * movementSpeed);
}
}
void BasicRotation()
{
float mouseX = Input.GetAxis("Mouse X") * Time.deltaTime * rotationSpeed;
transform.Rotate(new Vector3(0, mouseX, 0));
}
}
PhotonLobby
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
public class PhotonLobby : MonoBehaviourPunCallbacks
{
// Start is called before the first frame update
public static PhotonLobby lobby;
public GameObject battleButton;
RoomInfo[] room;
public GameObject cancelButtom;
private void Awake()
{
lobby = this;
}
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Debug.Log("the conection is stablished");
PhotonNetwork.AutomaticallySyncScene = true;
battleButton.SetActive(true);
}
public void OnBattleButtonClicked()
{
Debug.Log("llego aca paso algo en la el battle button click");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
//base.OnJoinRandomFailed(returnCode, message);
Debug.Log("failed joining the room");
CreateRoom();
}
void CreateRoom()
{
Debug.Log("llego a CreateRoom");
int randomRoomName = Random.Range(0, 10000);
RoomOptions roomOps = new RoomOptions()
{
IsVisible = true,
IsOpen = true,
MaxPlayers = (byte)MultiplayerSettings.multiplayerSettings.maxPlayers
};
PhotonNetwork.CreateRoom("Room" + randomRoomName, roomOps, null);
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
//base.OnCreateRoomFailed(returnCode, message);
Debug.Log("failed creating the room");
CreateRoom();
}
public void OnCancelButtonCliked()
{
Debug.Log("Llego OnCancelButtonCliked");
battleButton.SetActive(false);
cancelButtom.SetActive(true);
PhotonNetwork.LeaveRoom();
}
}
PhotonPlayer
using Photon.Pun;
using System.IO;
using UnityEngine;
public class PhotonPlayer : MonoBehaviour
{
// Start is called before the first frame update
private PhotonView PV;
public GameObject myAvatar;
public GameObject myMainCamera;
void Start()
{
PV = GetComponent<PhotonView>();
int spawnPicker = Random.Range(0, GameSetUp.GS.spawnPoints.Length);
if (PV.IsMine)
{
myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PlayerAvatar"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);
/*myAvatar = PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "Character 1"), GameSetUp.GS.spawnPoints[spawnPicker].position,
GameSetUp.GS.spawnPoints[spawnPicker].rotation, 0);*/
}
}
}
PhotonRoom
using Photon.Pun;
using Photon.Realtime;
using System.IO;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PhotonRoom : MonoBehaviourPunCallbacks, IInRoomCallbacks
{
// Start is called before the first frame update
public static PhotonRoom room;
private PhotonView PV;
public bool IsGameLoaded;
public int currentScene;
private Photon.Realtime.Player[] photonPlayers;
public int playersInRoom;
public int myNumberInRoom;
public int playerInGame;
private bool readyToCount;
private bool readyToStart;
public float startingTime;
private float lessThanMaxPlayer;
private float atMaxPlayer;
private float timeToStart;
private void Awake()
{
if(PhotonRoom.room == null)
{
PhotonRoom.room = this;
}
else
{
if(PhotonRoom.room != this)
{
Destroy(PhotonRoom.room.gameObject);
PhotonRoom.room = this;
}
}
DontDestroyOnLoad(this.gameObject);
}
public override void OnEnable()
{
base.OnEnable();
PhotonNetwork.AddCallbackTarget(this);
SceneManager.sceneLoaded += OnSceneFinishedLoading;
}
public override void OnDisable()
{
base.OnDisable();
PhotonNetwork.RemoveCallbackTarget(this);
SceneManager.sceneLoaded -= OnSceneFinishedLoading;
}
void Start()
{
PV = GetComponent<PhotonView>();
readyToCount = false;
readyToStart = false;
lessThanMaxPlayer = startingTime;
atMaxPlayer = 6;
timeToStart = startingTime;
}
// Update is called once per frame
void Update()
{
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
if(playersInRoom == 1)
{
RestartTimer();
}
if (!IsGameLoaded)
{
if (readyToStart)
{
atMaxPlayer -= Time.deltaTime;
lessThanMaxPlayer = atMaxPlayer;
timeToStart = atMaxPlayer;
}
else if (readyToCount)
{
lessThanMaxPlayer -= Time.deltaTime;
timeToStart = lessThanMaxPlayer;
}
Debug.Log("Displayer time to start to the players " + timeToStart );
if (timeToStart <=0)
{
StartGame();
}
}
}
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
Debug.Log("Se Unio a OnJoinedRoom");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom = photonPlayers.Length;
myNumberInRoom = playersInRoom;
PhotonNetwork.NickName = myNumberInRoom.ToString();
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible ("+playersInRoom+":"+MultiplayerSettings.multiplayerSettings.maxPlayers+")");
if(playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
else
{
StartGame();
}
}
public override void OnPlayerEnteredRoom(Photon.Realtime.Player newPlayer)
{
base.OnPlayerEnteredRoom(newPlayer);
Debug.Log("A new player has joined the room");
photonPlayers = PhotonNetwork.PlayerList;
playersInRoom++;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
Debug.Log("Displayer players in room out of max players possible (" + playersInRoom + ":" + MultiplayerSettings.multiplayerSettings.maxPlayers + ")");
if (playersInRoom > 1)
{
readyToCount = true;
}
if (playersInRoom == MultiplayerSettings.multiplayerSettings.maxPlayers)
{
readyToStart = true;
if (!PhotonNetwork.IsMasterClient)
{
return;
}
PhotonNetwork.CurrentRoom.IsOpen = false;
}
}
}
void StartGame()
{
IsGameLoaded = true;
if (!PhotonNetwork.IsMasterClient)
return;
if(MultiplayerSettings.multiplayerSettings.delayStart)
{
PhotonNetwork.CurrentRoom.IsOpen = false;
}
PhotonNetwork.LoadLevel(MultiplayerSettings.multiplayerSettings.multiplayerScene);
}
void RestartTimer()
{
lessThanMaxPlayer = startingTime;
timeToStart = startingTime;
atMaxPlayer = 6;
readyToCount = false;
readyToStart = false;
}
void OnSceneFinishedLoading(Scene scene, LoadSceneMode mode)
{
currentScene = scene.buildIndex;
if (currentScene ==MultiplayerSettings.multiplayerSettings.multiplayerScene)
{
IsGameLoaded = true;
if (MultiplayerSettings.multiplayerSettings.delayStart)
{
PV.RPC("RPC_loadedGameScene", RpcTarget.MasterClient);
}
else
{
RPC_CreatePlayer();
}
}
}
[PunRPC]
private void RPC_LoadedGameScene()
{
playerInGame++;
if (playerInGame == PhotonNetwork.PlayerList.Length)
{
PV.RPC("RPC_CreatePlayer",RpcTarget.All);
}
}
[PunRPC]
private void RPC_CreatePlayer()
{
PhotonNetwork.Instantiate(Path.Combine("PhotonPrefabs", "PhotonNetworkPlayer"), transform.position, Quaternion
.identity, 0);
}
}
GameSetUp
using UnityEngine;
public class GameSetUp : MonoBehaviour
{
// Start is called before the first frame update
public static GameSetUp GS;
public Transform[] spawnPoints;
private void OnEnable()
{
if (GameSetUp.GS == null)
{
GameSetUp.GS = this;
}
}
}
MultiplayerSettings
using UnityEngine;
public class MultiplayerSettings : MonoBehaviour
{
// Start is called before the first frame update
public static MultiplayerSettings multiplayerSettings;
public bool delayStart;
public int maxPlayers;
public int menuScene;
public int multiplayerScene;
private void Awake()
{
if(MultiplayerSettings.multiplayerSettings == null)
{
MultiplayerSettings.multiplayerSettings = this;
}
else
{
if(MultiplayerSettings.multiplayerSettings != this)
{
Destroy(this.gameObject);
}
}
DontDestroyOnLoad(this.gameObject);
}
}
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Acompáñanos en ésta nueva serie donde abarcaremos la creación de nuestro videojuego TPS en la modalidad Multijugador con Photon 2 en Unity 3D. La implementación multijugador es independiente del juego la haremos así para que puedas utilizarla en cualquier otro proyecto que requieras disfrútalo.
En pocas palabras, Photon Enterprise Cloud es como nuestra Photon Cloud pública bien establecida y agrega las siguientes características: se ejecuta en servidores dedicados, proporciona niveles de servicio garantizados (SLA) y soporte de alta prioridad. Otra gran ventaja: puede ejecutar su propia lógica de servidor autorizada a través de complementos.
Los escenarios típicos de Photon Enterprise Cloud son aplicaciones con 10 000 usuarios simultáneos o más, proyectos de juegos más grandes que necesitan una lógica de servidor autorizada o empresas cuyas políticas de cumplimiento las restringen a recursos dedicados.
Todos los productos de Photon Cloud se basan en una arquitectura de cliente a servidor, ¡la solución más estable para juegos multijugador! En las arquitecturas de igual a igual, los clientes a menudo no pueden conectarse debido a problemas de penetración de NAT. Este problema es aún peor en las redes móviles. Con Photon Cloud tus juegos siempre estarán conectados.
Nuestro equipo de operaciones supervisa los servidores las 24 horas del día, los 7 días de la semana y puede ampliar los recursos necesarios en cualquier momento. Ya sea que su juego necesite capacidad para cientos o cientos de miles de usuarios simultáneos: lo adaptamos a sus demandas.
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Acompañanos a ver éste nuevo tutorial donde añadimos interfaces UI Menú de opciones, sonido y transiciones desplegables para nuestro videojuego Third Person Shooter.
Para crear un nuevo proyecto en unity debes realizar los siguiente pasos:
El nombre por defecto para New Unity Project pero puede cambiarlo siempre que quiera. Escriba el nombre con el que quiere llamar a su proyecto en el campo Project name.
La localización por defecto para su carpeta personal en su ordenador, pero puede cambiarla. BIEN POR (a) Escriba aquí dónde quiere almacenar su proyecto en su ordenador en el campo Location. O (b) Haga clic en los tres puntos azules ‘…’. Esto mostrará el Finder de su ordenador (Mac OS X) o el Explorador de Archivos (Windows).
Entonces, en el Finder o en el Explorador de Archivos, seleccione la carpeta de proyecto en la que quiera guardar su nuevo proyecto, y seleccione “Elegir”.
Seleccione 3D o 2D para su tipo de proyecto. Por defecto es 3D, resaltado en rojo para mostrar que está seleccionado. (La opción 2D hace que el editor de Unity muestre sus características, y la opción 3D muestra las características 3D. Si no está seguro de qué elegir, déjelo en 3D; puede cambiar esta configuración más tarde.)
Hay una opción para seleccionar Asset packages… para incluir en su proyecto. Los paquetes de Assets son contenido pre-elaborado, como imágenes, estilos, efectos de iluminación y y controles de personaje en juego, entre otras útiles herramientas de creación del juego y contenidos. Los paquetes de assets ofrecidos aquí son gratuitos, empaquetados con Unity, y puede usarlos para comenzar con su proyecto. BIEN PUEDE: si no quiere importar esos assets empaquetados, o no está seguro, simplemente ignore esta opción; puede añadir estos assets y muchos otros posteriormente vía el editor de Unity. O: Si no quiere importar esos assets empaquetados ahora, seleccione Asset packages…_ para mostrar la lista de assets disponible, marque los que desee, y haga clic en Done.
Ahora seleccione Create project y ¡todo estará listo!
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
El nombre por defecto para New Unity Project pero puede cambiarlo siempre que quiera. Escriba el nombre con el que quiere llamar a su proyecto en el campo Project name.
La localización por defecto para su carpeta personal en su ordenador, pero puede cambiarla. BIEN POR (a) Escriba aquí dónde quiere almacenar su proyecto en su ordenador en el campo Location. O (b) Haga clic en los tres puntos azules ‘…’. Esto mostrará el Finder de su ordenador (Mac OS X) o el Explorador de Archivos (Windows).
Entonces, en el Finder o en el Explorador de Archivos, seleccione la carpeta de proyecto en la que quiera guardar su nuevo proyecto, y seleccione “Elegir”.
Seleccione 3D o 2D para su tipo de proyecto. Por defecto es 3D, resaltado en rojo para mostrar que está seleccionado. (La opción 2D hace que el editor de Unity muestre sus características, y la opción 3D muestra las características 3D. Si no está seguro de qué elegir, déjelo en 3D; puede cambiar esta configuración más tarde.)
Hay una opción para seleccionar Asset packages… para incluir en su proyecto. Los paquetes de Assets son contenido pre-elaborado, como imágenes, estilos, efectos de iluminación y y controles de personaje en juego, entre otras útiles herramientas de creación del juego y contenidos. Los paquetes de assets ofrecidos aquí son gratuitos, empaquetados con Unity, y puede usarlos para comenzar con su proyecto. BIEN PUEDE: si no quiere importar esos assets empaquetados, o no está seguro, simplemente ignore esta opción; puede añadir estos assets y muchos otros posteriormente vía el editor de Unity. O: Si no quiere importar esos assets empaquetados ahora, seleccione Asset packages…_ para mostrar la lista de assets disponible, marque los que desee, y haga clic en Done__.
Ahora seleccione Create project y ¡todo estará listo!
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Para renderizar cualquier objeto en la pantalla, el CPU tiene mucho trabajo que hacer: trabajar qué luces afecta ese objeto, configurar el shader y los parámetros del shader, y enviar comandos de dibujo al driver gráfico, que luego prepara los comandos para que sea enviado a la tarjeta gráfica.
Todo este uso del CPU “por objeto” es intensivo a los recursos, por lo que si usted tiene muchos objetos visibles, esto se puede agregar. Por ejemplo, si usted tiene miles de triángulos, es mucho más fácil en el CPU si todos están en un mesh, en vez de un mesh por triángulo (agregando hasta 1000 meshes). El precio de ambos escenarios en el GPU es muy similar, pero el trabajo hecho por el CPU para renderizar mil objetos (en vez de uno) es significativamente mayor.
Reduzca la cuenta visible de objetos. Para reducir la cantidad de trabajo que el CPU necesita hacer:
Combine objetos cerca juntos, ya sea manualmente, o utilizando el draw call batching de Unity.
Utilice menos materiales en sus objetos, colocando texturas en un texture atlas más grande.
Utilice menos cosas que cause que los objetos sean renderizados múltiples veces (como lo son los reflejos, sombras, y luces per-pixel).
Combine los objetos juntos para que cada mesh tenga al menos varios cientos de triángulos y utilice solo un Material para el mesh entero. Es importante que tenga en cuenta que combinar dos objetos que no compartan un material no le da a usted ningún incremento de rendimiento. La razón más común para tener múltiples materiales es que dos meshes no compartan la misma textura; entonces para optimizar el rendimiento del CPU, usted debe asegurarse que cualquier objeto que usted combine comparta las misma texturas.
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Ha jugado muchos videojuegos, pero mientras jugaba esos juegos vio un minimapa (o minimapa) en una de las esquinas de la pantalla del juego para guiarlo.
¿Sabes cómo se desarrollan los minimapas?
Los minimapas son una de las características importantes de los videojuegos que guían a los jugadores a encontrar el camino y los objetivos a alcanzar. Por otro lado, Reder Textures se crea y actualiza en tiempo de ejecución. En este blog, aprende el desarrollo de los minimapas con Render Texture en Unity. Echar un vistazo.
Render Texture es un tipo de textura que se puede renderizar. Las texturas de renderizado son tipos especiales de texturas que se crean y actualizan en tiempo de ejecución. Render Texture se utiliza para mejorar e implementar renderizado basado en imágenes, cámaras de vigilancia y mucho más.
Los juegos RTS a menudo requieren que el jugador realice un seguimiento de su movimiento de tropas y del enemigo, mientras microgestiona la recopilación de recursos, la construcción de bases y muchas otras facetas de su estrategia general.
Para ayudar a hacer frente a este exigente nivel de microgestión, el jugador tiene a su disposición varias herramientas, como la capacidad de crear grupos de control, guardar ubicaciones en el mapa y usar una gran cantidad de teclas de acceso rápido. Sin embargo, ninguna de estas herramientas supera la utilidad inigualable del minimapa.
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.
Hay una gran cantidad de videojuegos por ahí y en esta época de juegos móviles y en el hogar, las opciones nunca han sido tan grandes. Entonces, ¿cómo puede eliminar el ruido y encontrar lo «mejor de» para cualquier tema elegido? Bueno, estamos aquí para ayudar a celebrar y destacar algunos de los últimos, mejores e inolvidables juegos a lo largo de los años.
Para nuestra serie continua de artículos que describen los mejores videojuegos, esta vez nuestra atención se centra en los mejores juegos de disparos en tercera persona de todos los tiempos. Desde juegos de disparos caóticos hasta aventuras caprichosas, hay una buena opción para abrir el apetito.
Los juegos de disparos en tercera persona para PC se sumergen en la atmósfera del juego no tanto como sus contrapartes en la industria con una vista desde los ojos del héroe. Sin embargo, en los juegos de disparos donde la cámara está fija para el personaje principal, hay características únicas, por ejemplo, el ángulo de visión es más amplio, por lo que los enemigos a la vista son más, lo que significa que el enemigo no pasará desapercibido incluso en una situación en la que intentará acercarse sigilosamente por la espalda.
Código para habilitar opción de copiar y pegar todos los componentes de un Objeto en las opciones del Editor de Unity.
/*
Una pequeña pero muy útil extensión de editor simple para copiar
y pegar todos los componentes
author: Darwin Palma
*/
using UnityEngine;
using UnityEditor;
using System.Collections;
public class ComponentsCopier : EditorWindow
{
static Component[] copiedComponents;
[MenuItem("GameObject/Copy all components %&C")]
static void Copy()
{
copiedComponents = Selection.activeGameObject.GetComponents();
}
[MenuItem("GameObject/Paste all components %&P")]
static void Paste()
{
foreach (var targetGameObject in Selection.gameObjects)
{
if (!targetGameObject || copiedComponents == null) continue;
foreach (var copiedComponent in copiedComponents)
{
if (!copiedComponent) continue;
UnityEditorInternal.ComponentUtility.CopyComponent(copiedComponent);
UnityEditorInternal.ComponentUtility.PasteComponentAsNew(targetGameObject);
}
}
}
}
Síguenos en nuestro canal de YouTube dedicado a tecnología, marketplace de proyectos tecnológicos, cursos online y tutoriales de desarrollo de videojuegos. Ofrecemos consultoría en desarrollo de software, marketing online, servicios de TI, hosting web, dominios web y más.