For this lesson on how to make Among Us in Unity, we will go over how to create the report mechanic. This makes it so the player can press a button when they see a dead body and a message will then be sent to report the body.
Unlock Code and Member Content
AU_PlayerController.cs
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; public class AU_PlayerController : MonoBehaviour { [SerializeField] bool hasControl; public static AU_PlayerController localPlayer; //Components Rigidbody myRB; Animator myAnim; Transform myAvatar; //Player movement [SerializeField] InputAction WASD; Vector2 movementInput; [SerializeField] float movementSpeed; //Player Color [SerializeField] Color myColor; SpriteRenderer myAvatarSprite; //Role [SerializeField] bool isImposter; [SerializeField] InputAction KILL; float killInput; List<AU_PlayerController> targets; [SerializeField] Collider myCollider; bool isDead; [SerializeField] GameObject bodyPrefab; public static List<Transform> allBodies; List<Transform> bodiesFound; [SerializeField] InputAction REPORT; [SerializeField] LayerMask ignoreForBody; private void Awake() { KILL.performed += KillTarget; REPORT.performed += ReportBody; } private void OnEnable() { WASD.Enable(); KILL.Enable(); REPORT.Enable(); } private void OnDisable() { WASD.Disable(); KILL.Disable(); REPORT.Disable(); } // Start is called before the first frame update void Start() { if(hasControl) { localPlayer = this; } targets = new List<AU_PlayerController>(); myRB = GetComponent<Rigidbody>(); myAnim = GetComponent<Animator>(); myAvatar = transform.GetChild(0); myAvatarSprite = myAvatar.GetComponent<SpriteRenderer>(); if (!hasControl) return; if (myColor == Color.clear) myColor = Color.white; myAvatarSprite.color = myColor; allBodies = new List<Transform>(); bodiesFound = new List<Transform>(); } // Update is called once per frame void Update() { if (!hasControl) return; movementInput = WASD.ReadValue<Vector2>(); myAnim.SetFloat("Speed", movementInput.magnitude); if (movementInput.x != 0) { myAvatar.localScale = new Vector2(Mathf.Sign(movementInput.x), 1); } if(allBodies.Count > 0) { BodySearch(); } } private void FixedUpdate() { myRB.velocity = movementInput * movementSpeed; } public void SetColor(Color newColor) { myColor = newColor; if (myAvatarSprite != null) { myAvatarSprite.color = myColor; } } public void SetRole(bool newRole) { isImposter = newRole; } private void OnTriggerEnter(Collider other) { if (other.tag == "Player") { AU_PlayerController tempTarget = other.GetComponent<AU_PlayerController>(); if (isImposter) { if (tempTarget.isImposter) return; else { targets.Add(tempTarget); } } } } private void OnTriggerExit(Collider other) { if (other.tag == "Player") { AU_PlayerController tempTarget = other.GetComponent<AU_PlayerController>(); if (targets.Contains(tempTarget)) { targets.Remove(tempTarget); } } } private void KillTarget(InputAction.CallbackContext context) { if (context.phase == InputActionPhase.Performed) { //Debug.Log(targets.Count); if (targets.Count == 0) return; else { if (targets[targets.Count - 1].isDead) return; transform.position = targets[targets.Count - 1].transform.position; targets[targets.Count - 1].Die(); targets.RemoveAt(targets.Count - 1); } } } public void Die() { AU_Body tempBody = Instantiate(bodyPrefab, transform.position, transform.rotation).GetComponent<AU_Body>(); tempBody.SetColor(myAvatarSprite.color); isDead = true; myAnim.SetBool("IsDead", isDead); gameObject.layer = 9; myCollider.enabled = false; } void BodySearch() { foreach(Transform body in allBodies) { RaycastHit hit; Ray ray = new Ray(transform.position, body.position - transform.position); Debug.DrawRay(transform.position, body.position - transform.position, Color.cyan); if(Physics.Raycast(ray, out hit, 1000f, ~ignoreForBody)) { if (hit.transform == body) { //Debug.Log(hit.transform.name); //Debug.Log(bodiesFound.Count); if (bodiesFound.Contains(body.transform)) return; bodiesFound.Add(body.transform); } else { bodiesFound.Remove(body.transform); } } } } private void ReportBody(InputAction.CallbackContext obj) { if (bodiesFound == null) return; if (bodiesFound.Count == 0) return; Transform tempBody = bodiesFound[bodiesFound.Count - 1]; allBodies.Remove(tempBody); bodiesFound.Remove(tempBody); tempBody.GetComponent<AU_Body>().Report(); } }
AU_Body.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class AU_Body : MonoBehaviour { [SerializeField] SpriteRenderer bodySprite; public void SetColor(Color newColor) { bodySprite.color = newColor; } private void OnEnable() { if(AU_PlayerController.allBodies != null) { AU_PlayerController.allBodies.Add(transform); } } public void Report() { Debug.Log("Reported"); Destroy(gameObject); } }
using Photon.Chat; using Photon.Pun; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class PhotonChatManager : MonoBehaviour, IChatClientListener { #region Setup [SerializeField] GameObject joinChatButton; ChatClient chatClient; bool isConnected; [SerializeField] string username; public void UsernameOnValueChange(string valueIn) { username = valueIn; } public void ChatConnectOnClick() { isConnected = true; chatClient = new ChatClient(this); //chatClient.ChatRegion = "US"; chatClient.Connect(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdChat, PhotonNetwork.AppVersion, new AuthenticationValues(username)); Debug.Log("Connenting"); } #endregion Setup #region General [SerializeField] GameObject chatPanel; string privateReceiver = ""; string currentChat; [SerializeField] InputField chatField; [SerializeField] Text chatDisplay; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { if (isConnected) { chatClient.Service(); } if (chatField.text != "" && Input.GetKey(KeyCode.Return)) { SubmitPublicChatOnClick(); SubmitPrivateChatOnClick(); } } #endregion General #region PublicChat public void SubmitPublicChatOnClick() { if (privateReceiver == "") { chatClient.PublishMessage("RegionChannel", currentChat); chatField.text = ""; currentChat = ""; } } public void TypeChatOnValueChange(string valueIn) { currentChat = valueIn; } #endregion PublicChat #region PrivateChat public void ReceiverOnValueChange(string valueIn) { privateReceiver = valueIn; } public void SubmitPrivateChatOnClick() { if (privateReceiver != "") { chatClient.SendPrivateMessage(privateReceiver, currentChat); chatField.text = ""; currentChat = ""; } } #endregion PrivateChat #region Callbacks public void DebugReturn(DebugLevel level, string message) { //throw new System.NotImplementedException(); } public void OnChatStateChange(ChatState state) { if(state == ChatState.Uninitialized) { isConnected = false; joinChatButton.SetActive(true); chatPanel.SetActive(false); } } public void OnConnected() { Debug.Log("Connected"); joinChatButton.SetActive(false); chatClient.Subscribe(new string[] { "RegionChannel" }); } public void OnDisconnected() { isConnected = false; joinChatButton.SetActive(true); chatPanel.SetActive(false); } public void OnGetMessages(string channelName, string[] senders, object[] messages) { string msgs = ""; for (int i = 0; i < senders.Length; i++) { msgs = string.Format("{0}: {1}", senders[i], messages[i]); chatDisplay.text += "\n" + msgs; Debug.Log(msgs); } } public void OnPrivateMessage(string sender, object message, string channelName) { string msgs = ""; msgs = string.Format("(Private) {0}: {1}", sender, message); chatDisplay.text += "\n " + msgs; Debug.Log(msgs); } public void OnStatusUpdate(string user, int status, bool gotMessage, object message) { throw new System.NotImplementedException(); } public void OnSubscribed(string[] channels, bool[] results) { chatPanel.SetActive(true); } public void OnUnsubscribed(string[] channels) { throw new System.NotImplementedException(); } public void OnUserSubscribed(string channel, string user) { throw new System.NotImplementedException(); } public void OnUserUnsubscribed(string channel, string user) { throw new System.NotImplementedException(); } #endregion Callbacks }