I'm making a board game in Unity with multiple branching paths where the players can decide which one to follow. (Think the Mario Part game board) But the player input on which path to follow isn't working.
So I have a script that has the tokens follow a set path and (Linked List for the path) with a for loop to have the tokens move their allocated amount. Within the loop, I have an If statement that checks how many paths the tile has and if there are more than one if runs a separate script that pauses the game and offers a menu prompt for the players to pick one path or the other.
I've tried tossing in a few contitions for continuing the game within the loop but they either ignore the player input, are an input behind or just break the code.
`for (int i = 0; i < spacesToMove; i++)
{
if (final_Waypoint == null)
{
final_Waypoint = Starting_Waypoint;
}
else
{
if (final_Waypoint.Next_Waypoint == null || final_Waypoint.Next_Waypoint.Length == 0)
{
//we are overshooting the final waypoint, so just return some nulls in the array
//just break and we'll return the array, which is going to have nulls at the end.
Debug.Log(Current_Waypoint);
break;
}
else if (final_Waypoint.Next_Waypoint.Length > 1) // && if playerID == 0 so it only appears for players.
{
menu.Pause_for_Choice();
//if (menu.ButtonPress == true)
final_Waypoint = final_Waypoint.Next_Waypoint[menu.choice_int];
//***There's a bug here. It calls menu as per normal, and the game pauses.
//But when I click 'no', choice_int isn't updated first: this function finishes first,
//so this function gets old choice_int. THEN the button function executes.
Debug.Log("test 3 " + menu.choice_int);
}
else
{
final_Waypoint = final_Waypoint.Next_Waypoint[0];
}
}
listOfWaypoints[i] = final_Waypoint;
Debug.Log("i:" + i);
}
return listOfWaypoints;
}`
`{
public GameObject choice_Menu;
public bool isPaused = true;
public int choice_int=0;
public int choice_placeholder = 0;
public void Pause_for_Choice()
{
isPaused = true;
choice_Menu.SetActive(true);
Time.timeScale = 0;
}
public void Yes()
{
choice_placeholder = 0;
UnPause_Game();
}
public void No()
{
choice_placeholder = 1;
UnPause_Game();
}
public void UnPause_Game()
{
isPaused = false;
choice_Menu.SetActive(false);
Time.timeScale = 1;
}
}`
Related
I'm revising a code so that a camera will cycle through 3 different locations on a ship. The problem I've come across with this code is that it will only go to a 2nd location & stays there. It needs to cycle through but doesn't.
This is the code I'm working with:
public void CycleCameraView (Vector3 inputValue, int customPlayerInputEventType)
{
// Cycle the current camera view index to the next view.
currentCameraViewIndex = (currentCameraViewIndex + 1) % 3;
SetCurrentView(currentCameraViewIndex);
}
public int GetCurrentCameraViewIndex ()
{
return currentCameraViewIndex;
}
public int GetNextCameraViewIndex ()
{
return (currentCameraViewIndex + 1) % 3;
}
public void SetCurrentView(int viewIndex)
{
if (viewIndex >= 0 && viewIndex < 3 && shipCameraModule != null)
{
currentCameraViewIndex = viewIndex;
if (currentCameraViewIndex == 0)
{
// Camera view 1
// Set the camera parameters to match camera view 1
}
else if (currentCameraViewIndex == 1)
{
// Camera view 2
// Set the camera parameters to match camera view 2
}
else
{
// Camera view 3
// Set the camera parameters to match camera view 3
}
}
}
#endregion
}
First, you are repeating your code here which is obviously not a good practice.
(currentCameraViewIndex + 1) % 3;
Call the GetNextCameraViewIndex and bring the above logic there.
public void CycleCameraView (Vector3 inputValue, int customPlayerInputEventType)
{
// Cycle the current camera view index to the next view.
currentCameraViewIndex = GetNextCameraViewIndex;
SetCurrentView(currentCameraViewIndex);
}
public int GetNextCameraViewIndex ()
{
return (currentCameraViewIndex + 1) % 3; // Please correct if required, I'm not on a dev machine.
}
I think we need more stuff if you want us to be able to help you mate. Also, you shouyld definitly use a switch in your SetCurrentView(int viewIndex)
My problem is inside playmode I get expected array sequence: showing all gameobjects, RedCube, Interior, BlueCube, and then GreenCube. But, after I built it and test in my android. I get a different array sequence: showing all gameobjects, GreenCube, BlueCube, RedCube and then Interior. This screenshot shows the sequence of my array.image0.
There are 4 gameobjects under gameobject - Levels Image1. Added a script to Levels.... Image2complete scene screenshot.
public GameObject[] levels;
public Button levelBtn;
int i = 0;
private void Awake()
{
levels = GameObject.FindGameObjectsWithTag("levels");
Button btn = levelBtn.GetComponent<Button>();
}
// Start is called before the first frame update
void Start()
{
levelBtn.onClick.AddListener(onLevelclick);
}
public void onLevelclick()
{
if (i < levels.Length - 1)
{
i++;
}
else if (i >= levels.Length - 1)
{
i = 0;
}
Debug.Log(i);
if (i == 0)
{
levels[0].SetActive(true);
levels[1].SetActive(true);
levels[2].SetActive(true);
levels[3].SetActive(true);
}
else if (i == 1)
{
levels[0].SetActive(true);
levels[1].SetActive(false);
levels[2].SetActive(false);
levels[3].SetActive(false);
}
else if (i == 2)
{
levels[0].SetActive(true);
levels[1].SetActive(true);
levels[2].SetActive(false);
levels[3].SetActive(false);
}
else if (i == 3)
{
levels[0].SetActive(true);
levels[1].SetActive(true);
levels[2].SetActive(true);
levels[3].SetActive(false);
}
}
Inside this script I have a gameobject array. When I click the UIbutton, it will loop within the array.length.... But the array sequence is different from playmode and built. I couldn't figure out why?
If you assign gameobjects to levels in the unity inspector like image0, you don't need to this line.
levels = GameObject.FindGameObjectsWithTag("levels");
I have 3 checkboxes
public bool stateForward = false, stateReverse = false, stateRandom = false;
I want that i will be able to chose each time only one checkbox. But also in editor mode and also when the game is running. And when the game is running i want to make it effect on the game.
In the top of the script i added:
[ExecuteInEditMode]
I tried to do in the Start function
void Start()
{
while (true)
{
if (stateForward == true)
{
stateRandom = false;
stateReverse = false;
}
else if (stateReverse == true)
{
stateRandom = false;
stateForward = false;
}
else if (stateRandom == true)
{
stateForward = false;
stateReverse = false;
}
}
anims = GetComponent<Animations>();
waypoints = GameObject.FindGameObjectsWithTag("ClonedObject");
objectsToMove = GameObject.FindGameObjectsWithTag("Robots");
originalPosition = objectsToMove[0].transform.position;
}
But i'm getting on anims: Unreachable code detected
And in the Update function:
void Update()
{
if (MyCommands.walkbetweenwaypoints == true)
{
DrawLinesInScene();
anims.PlayState(Animations.AnimatorStates.RUN);
WayPointsAI();
}
}
And in WayPointsAI
private void WayPointsAI()
{
if (stateForward == true)
{
if (targetIndex == waypoints.Length)
targetIndex = 0;
}
if (stateReverse == true)
{
if (targetIndex == 0)
targetIndex = waypoints.Length;
}
waypoint = waypoints[targetIndex].transform;
float distance = Vector3.Distance(objectsToMove[0].transform.position, waypoint.transform.position);
objectsToMove[0].transform.rotation = Quaternion.Slerp(objectsToMove[0].transform.rotation, Quaternion.LookRotation(waypoint.position - objectsToMove[0].transform.position), rotationSpeed * Time.deltaTime);
//move towards the player
if (distance < 30)
{
objectsToMove[0].transform.position += objectsToMove[0].transform.forward * slowDownSpeed * Time.deltaTime;
}
else
{
objectsToMove[0].transform.position += objectsToMove[0].transform.forward * moveSpeed * Time.deltaTime;
}
if (distance < 2)
{
if (stateForward == true)
targetIndex++;
if (stateReverse == true)
targetIndex--;
}
}
First off, you are never going to get out of your Start() method. You have a while(true) loop that you never break out of, so you will be stuck there.
Instead of multiple checkboxes that you can only choose one of, just use an enumeration. Unity will give you a drop down and you can choose one of the three available states.
enum MyStateEnum{ Forward, Reverse, Random }
public MyStateEnum State;
If you want them to be exclusive, you should probably use a single enum field instead of three bool fields. Your enum would have values Forward, Reverse, and Random, while your MonoBehavior would have a single field of your enum type. This ensures that only one will be chosen at any given time, and the editor should show a drop-down for selecting which value rather than a series of checkboxes. This not only fixes the editor UI issue, but will also lead to cleaner code with fewer potential bugs.
I am working on an RPG and started working on ability cooldowns. I have a player that is controlled by the user (player1), and a player controlled by the computer (player2) for testing purposes. The cooldown for abilities work perfectly for the user controlled player, but when it comes to the AI, the computer will not execute the ability unless the computer goes first (when the ability is off cooldown by default). Below is the code I think is relevant to the question, but if more information is needed I will update the post.
The ability class:
using UnityEngine;
public class attackList : MonoBehaviour{
public int dmg;
public float coolDown;
public float _attackTimer;
public void Attack1(basePlayer user, basePlayer target, int D)
{
coolDown = 2.5f;
if (user._attackTimer == 0)
{
dmg = D;
user._attackTimer = coolDown;
target.curHealth -= dmg;
}
}
public void cooldown(basePlayer user)
{
if (user._attackTimer > 0) {
user._attackTimer -= Time.deltaTime;
if (user._attackTimer < 0) {
user._attackTimer = 0;
}
}
}
}
The attack logic class:
public class attackLogic : MonoBehaviour {
private attackList _attackList = new attackList();
private playerList _playerList = new playerList();
public bool player1_turn = false; //player1 is not allowed to go first by default
public bool player2_turn = false; //player2 is not allowed to go first by default
void Start()
{
int rnd = Random.Range (1,3); // random value between 1 and 2 generated, which will determine what player goes first
if (rnd == 1)
{
player1_turn = true;
}
if (rnd == 2)
{
player2_turn = true;
}
//current health set to the maximum health at the beginning of each fight
_playerList.player1.curHealth = _playerList.player1.maxHealth;
_playerList.player2.curHealth = _playerList.player2.maxHealth;
}
void Update()
{
Logic(); //run through the logic of the battle
}
public void Logic()
{
if (player1_turn == true)
{
_attackList.cooldown(_playerList.player1);
if (Input.GetKeyUp("1"))
{
_attackList.Attack1(_playerList.player1, _playerList.player2, 5);
player1_turn = false;
player2_turn = true;
}
}
if (player2_turn == true)
{
_attackList.cooldown(_playerList.player2);
_attackList.Attack1(_playerList.player2, _playerList.player1, 5);
player1_turn = true;
player2_turn = false;
}
}
}
1) I have a nasty suspicion that the actual problem is in Time.deltaTime, but you didn't show the code so I can't confirm this.
2) Since you have time-based code here you can't expect it to behave the same when you step through the code. Thus it often helps to dust off some of the old techniques--namely, print statements. Of course things have changed enough over the years that it's become write but the ideas still work. Take a part of the screen that isn't important to what you're testing and write the variables out that are involved in what you are doing. I think you'll find player 2 is cooling down extremely slowly.
3) I think you need a better understanding of objects. You appear to be simply using them as containers. I also dislike player1 and player2--you should simply have a list of players. Remember how the WOPR was defeated in War Games?--that can be very useful at times in balancing things.
I'm making a menu for an Android 2d app, I have a bunch of UI panels in multiple menu's and when I press the next right or previous left button the script should set the next panel active and deactive the previous panel, I've tried doing this with a public class with gameobjects but that didn't work and thought a list should work.
In the Unity editor I've set the size to 4 and dragged 4 panels into the script
and I'm getting this error:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
Here is the relevant part of the script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MenuControl : MonoBehaviour
{
//Buttons
public GameObject ShipUpgradeRight;
public GameObject ShipUpgradeLeft;
//Ships
private int shipUpgradeSelected = 0;
List<GameObject> ShipList = new List<GameObject>();
public void Keyword (string keyword)
{
if (keyword == "ShipUpgradeLeft") {
shipUpgradeSelected--;
ShipList[shipUpgradeSelected].SetActive (true);
ShipList[shipUpgradeSelected+1].SetActive (false);
}
if (keyword == "ShipUpgradeRight") {
shipUpgradeSelected--;
CheckShip ();
ShipList[shipUpgradeSelected].SetActive (true);
ShipList[shipUpgradeSelected-1].SetActive (false);
}
}
}
Based on your comments and the actual question I see one possible problem.
The value of shipUpgradeSelected never gets increased. Moreover, shipUpgradeSelected has zero as initial value.
public void Keyword (string keyword)
{
if (keyword == "ShipUpgradeLeft") {
shipUpgradeSelected--;
ShipList[shipUpgradeSelected].SetActive (true);
ShipList[shipUpgradeSelected+1].SetActive (false);
}
if (keyword == "ShipUpgradeRight") {
shipUpgradeSelected--;
CheckShip ();
ShipList[shipUpgradeSelected].SetActive (true);
ShipList[shipUpgradeSelected-1].SetActive (false);
}
}
When keyword equals to ShipUpgradeRight or ShipUpgradeLeft the value of shipUpgradeSelected is decreased (so it's less than zero). And then you try to access the item of list at index that is less than zero.
But this is first problem.
Also you don't clamp (or don't cycle) value of shipUpgradeSelected. So for example you have
if (keyword == "ShipUpgradeRight") {
shipUpgradeSelected++;
CheckShip ();
ShipList[shipUpgradeSelected].SetActive (true);
ShipList[shipUpgradeSelected-1].SetActive (false);
}
If call Keyword("ShipUpgradeRight"); five times (for example), the value of shipUpgradeSelected is 5. And again it's out of range. So you need to decide how to clamp value of this variable.
This code works perfect:
public void Keyword(string keyword) {
if (keyword == "ShipUpgradeLeft") {
shipUpgradeSelected--;
if (shipUpgradeSelected < 0) {
shipUpgradeSelected = 0;
return;
}
ShipList[shipUpgradeSelected].SetActive(true);
if (shipUpgradeSelected + 1 < ShipList.Count) ShipList[shipUpgradeSelected + 1].SetActive(false);
else ShipList[0].SetActive(false);
}
if (keyword == "ShipUpgradeRight") {
shipUpgradeSelected++;
if (shipUpgradeSelected >= ShipList.Count) {
shipUpgradeSelected = ShipList.Count - 1;
return;
}
ShipList[shipUpgradeSelected].SetActive(true);
if (shipUpgradeSelected > 0) ShipList[shipUpgradeSelected - 1].SetActive(false);
else ShipList[ShipList.Count-1].SetActive(false);
}
}
but if i would start over i'd do it like this:
private void Start()
{
ShipUpgradeLeft.GetComponent<Button>().onClick.AddListener(() => { Previous(); });
ShipUpgradeRight.GetComponent<Button>().onClick.AddListener(() => { Next(); });
}
public void Next()
{
ShipList[shipUpgradeSelected].SetActive(false);
shipUpgradeSelected = Mathf.Clamp(shipUpgradeSelected++, 0, ShipList.Count - 1);
ShipList[shipUpgradeSelected].SetActive(true);
}
public void Previous()
{
ShipList[shipUpgradeSelected].SetActive(false);
shipUpgradeSelected = Mathf.Clamp(shipUpgradeSelected--, 0, ShipList.Count - 1);
ShipList[shipUpgradeSelected].SetActive(true);
}
Thanks to walther and d12frosted for helping me solve the issue