I have a script for gun switching, it have an array to get the MeshRenderer component of all elements, then, i can enable the element that i want, but i cannot disable the others.
public class TrocarArma : MonoBehaviour
{
[Header("References")]
public int choosenGun = 0;
[Space(10)]
[SerializeField] MeshRenderer[] meshes = new MeshRenderer[4];
void Start()
{
SelectWeapon();
}
void Update()
{
ChangeGun();
}
void SelectWeapon()
{
int gunCount = 0;
meshes[0] = GameObject.Find("GravityGun").GetComponent<MeshRenderer>();
meshes[1] = GameObject.Find("IronBar").GetComponent<MeshRenderer>();
meshes[2] = GameObject.Find("Tablet").GetComponent<MeshRenderer>();
meshes[3] = null; //Will be filled later.
foreach(Transform gun in transform)
{
if (gunCount == choosenGun)
{
meshes[choosenGun].enabled = true;
}
else
{
///Code to make the others array meshes elements MeshRenderers disable.
}
gunCount++;
}
}
void ChangeGun()
{
int previousWeapon = choosenGun;
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if(choosenGun >= transform.childCount -1)
{
choosenGun = 0;
}
else
{
choosenGun++;
}
}
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (choosenGun <= 0)
{
chooseGun = transform.childCount - 1;
}
else
{
chooseGun--;
}
}
if (previousWeapon != chooseGun)
{
SelectWeapon();
}
}
}
I simply not used SetActive(true)/(false) because I need my tablet active to upgrade my defenses. The video that i make this script: https://www.youtube.com/watch?v=Dn_BUIVdAPg , thanks for reading!
You have strange logic inside void SelectWeapon() method. But, I dare to suggest that the following code can help you:
foreach(Transform gun in transform)
{
if (gunCount == choosenGun)
{
meshes[choosenGun].enabled = true;
}
else
{
meshes[gunCount].enabled = false;
}
gunCount++;
}
or
foreach(Transform gun in transform)
{
switch(gunCount)
{
case 0:
meshes[choosenGun].enabled = true;
break;
default:
meshes[gunCount].enabled = false;
break;
}
gunCount++;
}
By the way:
meshes[3] = null; will throw an exception when you try to access the .enabled property. It is better not to allow such null elements, or always to check for null.
Related
I've been trying to implement a dialogue system which will let select a choice in a dialogue. Unity shows no errors, dialogue choices are displayed correctly, and yet a weird thing happens - when I press down arrow key (which is supposed to change the selected choice) the othe choices isn't highlighted and is shown just for a second.
Here is the code for the choice box:
public class ChoiceBox : MonoBehaviour
{
[SerializeField] ChoiceText choiceTextPrefab;
bool choiceSelected = false;
List<ChoiceText> choiceTexts;
int currentChoice;
public IEnumerator ShowChoices(List<string> choices, Action<int> onChoiceSelected)
{
choiceSelected = false;
currentChoice = 0;
gameObject.SetActive(true);
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
choiceTexts = new List<ChoiceText>();
foreach (var choice in choices)
{
var choiceTextObj = Instantiate(choiceTextPrefab, transform);
choiceTextObj.TextField.text = choice;
choiceTexts.Add(choiceTextObj);
}
yield return new WaitUntil(() => choiceSelected == true);
onChoiceSelected?.Invoke(currentChoice);
Debug.Log("choice is selected"); //this is showing in the console, but the choice box doesn't disappear
gameObject.SetActive(false);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.DownArrow))
++currentChoice;
else if (Input.GetKeyDown(KeyCode.UpArrow))
--currentChoice;
currentChoice = Mathf.Clamp(currentChoice, 0, choiceTexts.Count - 1);
for (int i = 0; i < choiceTexts.Count; i++)
{
choiceTexts[i].SetSelected(i == currentChoice);
}
if (Input.GetKeyDown(KeyCode.Return))
choiceSelected = true;
}
Then for the dialogue manager:
public class DialogueManager : MonoBehaviour
{
public Text dialogueName;
public Text dialogueText;
public static DialogueManager instance;
public int activeLineIndex;
public Animator anim;
public float typingSpeed = 0.2f;
public bool canPressE = true;
public bool makeYourChoice = false;
List<string> choices = new List<string>();
List<int> Action = new List<int>();
public bool dialogueFinished = false;
[SerializeField] ChoiceBox choiceBox;
public void EnqueueDialogue(DialogueBase db)
{
canPressE = false;
dialogueInfo.Clear();
foreach(DialogueBase.Info info in db.dialogueInfo)
{
dialogueInfo.Enqueue(info);
}
anim.SetBool("isopen", true);
DequeueDialogue();
}
public void DequeueDialogue()
{
if (dialogueInfo.Count == 0)
{
dialogueFinished = true;
StartCoroutine(DisplayChoices(choices));
makeYourChoice = true;
return;
}
if (makeYourChoice)
{
EndDialogue();
return;
}
StopAllCoroutines();
DialogueBase.Info info = dialogueInfo.Dequeue();
dialogueName.text = info.myName;
dialogueText.text = info.dialogueText;
StartCoroutine(TypeText(info));
}
public IEnumerator DisplayChoices(List<string> choices = null, Action<int> onChoiceSelected = null)
{
if ((choices != null) && choices.Count > 1)
{
yield return choiceBox.ShowChoices(choices, onChoiceSelected);
}
else
{
yield return null;
}
}
IEnumerator TypeText(DialogueBase.Info info)
{
dialogueText.text = "";
foreach (char letter in info.dialogueText.ToCharArray())
{
yield return new WaitForSeconds(typingSpeed);
dialogueText.text += letter;
yield return null;
}
}
void EndDialogue()
{
anim.SetBool("isopen", false);
}
public void GetNextLine()
{
if (!canPressE)
{
DequeueDialogue();
Debug.Log("dalshe");
}
}
public void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GetNextLine();
}
}
public Queue<DialogueBase.Info> dialogueInfo;
public void Start()
{
dialogueInfo = new Queue<DialogueBase.Info>();
canPressE = true;
}
public void Awake()
{
if (instance != null)
{
Debug.Log("fix this" + gameObject.name);
}
else
{
instance = this;
}
}
}
For the choice text:
public class ChoiceText : MonoBehaviour
{
Text myText;
TextMeshProUGUI choiceText;
private void Awake()
{
choiceText = GetComponent<TextMeshProUGUI>();
}
public void SetSelected(bool selected)
{
choiceText.color = (selected) ? GlobalSettings.i.HighlightedColor: Color.blue;
}
public TextMeshProUGUI TextField => choiceText;
}
And for the object which the player collides and has a dialogue with:
if (Input.GetKeyDown(KeyCode.E) )
{
onTriggerEnter.Invoke();
dialogueStarted = true;
Debug.Log("запускаем диалог");
}
if (dialogueStarted && dM.dialogueFinished)
StartCoroutine(ShowDialogueOptions());
public IEnumerator ShowDialogueOptions()
{
int selectedChoice = 1;
Debug.Log("show choices");
yield return DialogueManager.instance.DisplayChoices(new List<string> { "Yes", "No" }, (choiceIndex) => selectedChoice = choiceIndex);
if(selectedChoice == 0) //"Yes"
{
Debug.Log("Cool"); //this is shown in the console
}
else if (selectedChoice == 1) //"No"
{
Debug.Log("You suck"); //this is never shown in the console
}
Only one choice ("No") is highlighted with blue, but the other one isn't showing at all. However, when I press down arrow key, it is shown in white colour just for a moment so that it's barely visible. What is shown in the console is marked in comments. Thank you all in advance.
I wanted to add multiplayer to my game but i quickly faced many many problems, i cant find any clear solution online. i made a weapon script where the player can shoot and reload.
problems:
when i shoot, on 1 screen both players shoot, but at the other screen nothing happens
when i swap weapons, on 1 screen both players swap weapons, on the second screen nothing happens
note: im still a complete beginner so go easy on me please :)) thanks!
weapon script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using Photon.Pun;
public class weaponScript : MonoBehaviour
{
public weaponSO weaponStats;
public GameObject reloadingText;
public TMP_Text ammoValue;
public Transform firePoint;
public GameObject bulletPrefab;
public float bulletForce = 2f;
public bool isShooting;
public float pistolDamage;
public int currentAmmoClip = 1;
public int maxAmmoClip;
public int currentReserve = 1;
public int maxReserve;
public float reloadTime = 2f;
public bool isReloading = false;
public int bulletsShot;
public float startingDamage;
PhotonView view;
public void Start()
{
view = GetComponent<PhotonView>();
if(view.IsMine)
{
view.RPC("Update", RpcTarget.AllBuffered);
}
WeaponStats();
currentAmmoClip = maxAmmoClip;
currentReserve = maxReserve;
bulletsShot = maxAmmoClip - currentAmmoClip;
isShooting = false;
weaponStats.damage = startingDamage;
}
[PunRPC]
public void Update()
{
ammoValue.text = currentAmmoClip.ToString("0") + "/" + currentReserve.ToString("0");
if (Input.GetKeyDown(KeyCode.R))
{
if(currentReserve <= 0)
{
return;
}
if (currentAmmoClip == maxAmmoClip && !isReloading)
{
return;
}
else
{
StartCoroutine(Reload());
return;
}
}
if(Input.GetButtonDown("Fire1") && currentAmmoClip >= 1)
{
if(isReloading == false)
{
bulletsShot += 1;
currentAmmoClip -= 1;
isShooting = true;
Shoot();
FindObjectOfType<AudioManager>().Play("shot1");
return;
}
}
if(isReloading)
return;
if(currentAmmoClip <= 0 && currentReserve >= 1)
{
StartCoroutine(Reload());
return;
}
}
IEnumerator Reload()
{
reloadingText.SetActive(true);
isReloading = true;
yield return new WaitForSeconds(reloadTime);
if(currentReserve <= bulletsShot)
{
currentAmmoClip += currentReserve;
currentReserve = 0;
}
else
{
currentReserve -= bulletsShot;
currentAmmoClip = maxAmmoClip;
}
bulletsShot = 0;
reloadingText.SetActive(false);
isReloading = false;
}
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firePoint.up * bulletForce, ForceMode2D.Impulse);
}
public void WeaponStats()
{
pistolDamage = weaponStats.initialDamage;
maxAmmoClip = weaponStats.maxAmmoClip;
maxReserve = weaponStats.maxReserve;
reloadTime = weaponStats.reloadTime;
bulletForce = weaponStats.bulletForce;
startingDamage = weaponStats.initialDamage;
}
}
weapon holder:
using UnityEngine;
public class WeaponHolder : MonoBehaviour
{
public int selectedWeapon = 0;
void Start()
{
SelectWeapon();
}
void Update()
{
if(FindObjectsOfType<weaponScript>()[0].isReloading == true)
{
return;
}
else
{
switchWeapon();
}
}
public void switchWeapon()
{
int previousSelectedWeapon = selectedWeapon;
if(Input.GetAxis("Mouse ScrollWheel") > 0f)
{
if(selectedWeapon >= transform.childCount - 1)
{
selectedWeapon = 0;
}
else
{
selectedWeapon++;
}
}
if(Input.GetAxis("Mouse ScrollWheel") < 0f)
{
if(selectedWeapon <= 0)
{
selectedWeapon = transform.childCount - 1;
}
else
{
selectedWeapon--;
}
}
if(previousSelectedWeapon != selectedWeapon)
{
SelectWeapon();
}
}
public void SelectWeapon()
{
int i = 0;
foreach (Transform weapon in transform)
{
if(i == selectedWeapon)
{
weapon.gameObject.SetActive(true);
}
else
{
weapon.gameObject.SetActive(false);
}
i++;
}
}
}
i tried adding
if(view.IsMine == true)
{
Debug.Log("true");
}
else
{
Debug.Log("false");
}
but nothing happened and i couldnt shoot anymore. thanks for reading
The problem is you don't sync anything in your game. This means the other computer can't know what it has to do.
Whenever you want to sync something you have to call an RPC function.
Maybe watch some tutorials about how to do this properly and how to set up a simple multiplayer lobby.
EDIT:
What the other comments above mentioned with .IsMine is true, but you're doing it wrong. You have to call this in start or awake and whenever the view is not yours you disable the camera of the person only and disable shooting. Its important to only do this on your computer! If you are not doing everyone will shoot when you press Shoot and everyone will walk when you walk.
I am working on a 2D, topdown, roguelike game but i got stuck when i tried to make a shooting system.
when i run it and press the arrow keys, the bullet spawns and points in the right direction. It juste doesn't move in any way.
This is my code and i hope someone can figure it out. Btw, everything is connected. The player and the bullet prefab.
using System.Collections;
using System.Linq;
using UnityEngine;
namespace Assets.Scripts
{
[RequireComponent(typeof(Player))]
public class PlayerShootController : ShootControllerBase
{
[SerializeField]
private int _numberOfBombs;
public int NumberofBombs
{
get { return _numberOfBombs; }
set { _numberOfBombs = value; }
}
[SerializeField]
private PlayerHeadController _headObject;
public PlayerHeadController HeadObject
{
get { return _headObject; }
set { _headObject = value; }
}
[SerializeField]
private Bomb _bombPrefab;
public Bomb BombPrefab
{
get { return _bombPrefab; }
set { _bombPrefab = value; }
}
public bool IsShooting { get; private set; }
private KeyCode _shootKey;
private Vector2 _shootDirection;
private Player _player;
public override void Start()
{
base.Start();
_player = GetComponent<Player>();
}
public override void Update()
{
base.Update();
if (IsShooting)
{
SetHeadDirection(_shootKey);
return;
}
if (InputHelpers.IsAnyKey(KeyCode.UpArrow, KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow))
{
if (Input.GetKey(KeyCode.UpArrow))
{
_shootDirection = new Vector2(0, BulletSpeed);
_shootKey = KeyCode.UpArrow;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
_shootDirection = new Vector2(0, -BulletSpeed);
_shootKey = KeyCode.DownArrow;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
_shootDirection = new Vector2(-BulletSpeed, 0);
_shootKey = KeyCode.LeftArrow;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
_shootDirection = new Vector2(BulletSpeed, 0);
_shootKey = KeyCode.RightArrow;
}
StartCoroutine(Shoot());
}
if (NumberofBombs > 0 && InputHelpers.IsAnyKeyDown(KeyCode.LeftShift, KeyCode.RightShift, KeyCode.E))
{
var bomb = (Bomb) Instantiate(BombPrefab);
bomb.transform.position = transform.position;
NumberofBombs--;
}
}
IEnumerator Shoot()
{
IsShooting = true;
while (Input.GetKey(_shootKey))
{
var bullet = (Rigidbody2D)Instantiate(BulletPrefab);
bullet.GetComponent<BulletScript>().Shooter = transform.gameObject;
bullet.transform.position = transform.position;
if (_shootDirection.y > 0)
{
bullet.transform.Rotate(0, 0, -90);
}
else if (_shootDirection.y < 0)
{
bullet.transform.Rotate(0, 0, 90);
}
else if (_shootDirection.x > 0)
{
TransformHelpers.FlipX(bullet.gameObject);
}
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
if (ShootClips.Any())
{
var clipToPlay = ShootClips[Random.Range(0, ShootClips.Count)];
clipToPlay.pitch = Random.Range(MinShootPitch, MaxShootPitch);
clipToPlay.Play();
}
yield return new WaitForSeconds(ShootingSpeed);
}
IsShooting = false;
//Reset head flipping
if (_headObject.transform.localScale.x < 0)
{
TransformHelpers.FlipX(_headObject.gameObject);
}
}
private void SetHeadDirection(KeyCode shootKey)
{
switch (shootKey)
{
case KeyCode.UpArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Up);
break;
case KeyCode.DownArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Down);
break;
case KeyCode.LeftArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Left);
break;
case KeyCode.RightArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Right);
break;
}
}
}
}
try this:
bullet.AddForce(_shootDirection*moveSpeed*Time.deltaTime);
instead of this:
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
tweak the speed for desired result, and if you want the bullet to follow the player you will need to update the shoot direction every certain time with a couroutine
Im not really sure whats wrong, I'm pretty inexperienced with C#, and i posted this with everyone saying there isn't enough context, so Im posting the whole script. It isn't that long though, I just need this help!
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class MusicPlayer : MonoBehaviour {
public GUISkin skin;
public Song[] playlist;
public AudioClip mlgSong;
public AudioSource fastSource;
int currentSongID;
bool isPlaying;
[System.NonSerialized]
public bool fastMode = false;
string currentSongCredits;
//Song credits
float timer = 0;
float slidePosition;
float slidePositionMax = 20;
void Start() {
slidePosition = slidePositionMax;
ShuffleSongs();
audio.clip = playlist[0].clip;
currentSongID = 0;
isPlaying = audio.isPlaying;
if (!GameSettings.music) {
fastSource.Stop();
}
}
void Update() {
if ((!audio.isPlaying || GameSettings.keybinds.GetKeyDown("nextsong")) && isPlaying) {
if (currentSongID<playlist.Length-1) {
currentSongID++;
} else {
currentSongID = 0;
}
audio.clip = playlist[currentSongID].clip;
slidePosition = slidePositionMax;
Play (); //The error is here...
}
if ((!audio.isPlaying || GameSettings.keybinds.GetKeyDown("lastsong")) && isPlaying) {
if (currentSongID<playlist.Length+1) {
currentSongID++;
} else {
currentSongID = playlist.Length;
}
audio.clip = playlist[currentSongID].clip;
slidePosition = slidePositionMax;
Play (); //The error is also here.
}
//Timer
if (timer > 0) {
timer -= Time.deltaTime;
}
if (fastMode && fastSource.volume < 1) {
fastSource.volume = Mathf.Min(1,fastSource.volume + Time.deltaTime * 0.25f);
audio.volume = 0.5f - fastSource.volume/2;
}
if (!fastMode && fastSource.volume > 0) {
fastSource.volume = Mathf.Max(0,fastSource.volume - Time.deltaTime * 0.5f);
audio.volume = 0.5f - fastSource.volume/2;
}
if (timer > 0) {
slidePosition = Mathf.Lerp(slidePosition,0,Time.deltaTime);
} else {
slidePosition = Mathf.Lerp(slidePosition,slidePositionMax,Time.deltaTime);
}
}
public void Pause() {
Play (playlist[currentSongID].name);
}
public void Play(string credits) {
currentSongCredits = "Now playing: " + credits;
if (FindObjectOfType<MlgMode>() != null) {//IS MLG MODE
audio.clip = mlgSong;
currentSongCredits = "Now playing: xXxSW3GST3PxXx";
FindObjectOfType<MlgMode>().StartTheShit();//Start the wubs
}
isPlaying = true;
if (!audio.mute) {
timer = 8;
}
audio.Play();
}
void OnGUI() {
if (slidePosition < slidePositionMax-0.1f) {
GUI.skin = skin;
GUIStyle style = new GUIStyle(GUI.skin.label);
style.fontSize = 16;
style.alignment = TextAnchor.MiddleRight;
Rect rect = new Rect(0,Screen.height-30+slidePosition,Screen.width,30);
//GUIX.ShadowLabel(rect,currentSongCredits,style,1);
GUILayout.BeginArea(rect);
GUILayout.FlexibleSpace (); //Push down
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace(); //Push to the right
GUILayout.Label(currentSongCredits,GUI.skin.GetStyle("SoundCredits"),GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
void ShuffleSongs() {
//Shuffle playlist using Fisher-Yates algorithm
for (int i = playlist.Length;i > 1;i--) {
int j = Random.Range(0,i);
Song tmp = playlist[j];
playlist[j] = playlist[i - 1];
playlist[i - 1] = tmp;
}
}
}
[System.Serializable]
public class Song {
public string name;
public AudioClip clip;
}
Your Play method is declared like this:
public void Play(string credits)
but you are calling it like this:
Play();
You need to include a string as a parameter when you call it.
Play("White and Nerdy - Weird Al Yankovic");
Your Play(string credits) method is expecting a string called credits. Since you call Play() without putting a string there, it is giving you an error.
What it is looking for is an overloaded method, another form of Play() without the string and when it doesn't find that you receive that error.
i already make the player character to move to it is destination (animate the character to move to that destination), i wanted to disable the GUI button when the player character is moving, but i can't get it and work it out. Could you guys help me?
Here is the code:
public class UserPlayer : Player
{
public override void TurnUpdate()
{
//Moving animation
if (positionQueue.Count > 0)
{
GUI.enabled = false; // This is the one that i want when the character still moving (animation still moving), disabled the GUI. But i can't get it
transform.position += (positionQueue[0] - transform.position).normalized * moveSpeed * Time.deltaTime;
if (Vector3.Distance(positionQueue[0], transform.position) <= 0.1f)
{
transform.position = positionQueue[0];
positionQueue.RemoveAt(0);
if (positionQueue.Count == 0)
{
actionPoints--;
}
}
}
base.TurnUpdate();
}
public override void TurnOnGUI()
{
base.TurnOnGUI();
}
}
public class Player : MonoBehaviour
{
//for movement animation
public List<Vector3> positionQueue = new List<Vector3>();
public virtual void TurnUpdate()
{
if (actionPoints <= 0)
{
actionPoints = 2;
magicAttacking = false;
moving = false;
attacking = false;
GameManager.instance.NextTurn();
}
}
public virtual void TurnOnGUI()
{
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2)
{
//ToolTip Text
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
GUI.tooltip = null;
//Move Button
if (move)
{
if (!moving)
{
GameManager.instance.RemoveTileHighlights();
moving = true;
attacking = false;
GameManager.instance.HighlightTilesAt(gridPosition, Color.blue, movementPerActionPoint);
}
else
{
moving = false;
attacking = false;
GameManager.instance.RemoveTileHighlights();
}
}
}
Your question has been already made, take a look here.
Adapt your code in this way:
public virtual void TurnOnGUI() {
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2) {
...
if(!moving) {
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
}
...
}
}