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)
Related
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;
}
}`
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");
Hi,
Im working on Visual Studio Winforms and I'm trying to build tic-tac-toe.
I got stuck in the Check if player win method.
I have tried to do that in activated. little example:
private void StartForm_Activated(object sender, EventArgs e)
{
if ((_pcb1.Image == imagecircle) && (_pcb2.Image == imagecircle) && (_pcb3.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb4.Image == imagecircle) && (_pcb5.Image == imagecircle) && (_pcb6.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
if ((_pcb7.Image == imagecircle) && (_pcb8.Image == imagecircle) && (_pcb9.Image == imagecircle))
{
MessageBox.Show("You Win!");
}
}
(I know that there are more situations to win).
It's never get into the method, I trying to find a method that active always when the form is open. please help :)
You should check player's victory after each move of that player. I assume, that your players make their moves by clicking on "Make a Move" button or clicking on the game field. Also I assume, that you have Click event of your button or game field. So you should paste your check code in Click event of your button or game field.
Here is some code that will extend to whatever game size:
public class Level
{
private readonly Team[,] _game;
public Level(int extent)
{
_game = new Team[extent, extent];
}
public bool HasWon(Team team)
{
var yMax = GetYMax();
var xMax = GetXMax();
var won = false;
// check horizontally
for (var y = 0; y < yMax; y++)
{
won = false;
for (var x = 0; x < xMax; x++)
won |= _game[y, x] == team;
if (won) return true;
}
// TODO check vertically
// TODO check diagonally
return won;
}
public void SetTile(Team team, int x, int y)
{
var xMax = GetXMax();
var yMax = GetYMax();
if ((x < 0) || (x > xMax))
throw new ArgumentOutOfRangeException("x");
if ((y < 0) || (y > yMax))
throw new ArgumentOutOfRangeException("y");
_game[y, x] = team;
}
private int GetXMax()
{
var xMax = _game.GetUpperBound(1);
return xMax;
}
private int GetYMax()
{
var yMax = _game.GetUpperBound(0);
return yMax;
}
}
public enum Team
{
Red,
Blue
}
Things for you to do:
implement logic for checking if a team has won vertically or diagonally
implement your game using this class, drawing pictures according the array _game (make it available publicly)
study the | OR operator to understand how it's used in here : https://msdn.microsoft.com/en-us/library/6373h346.aspx
further debug the code (I haven't :)
If you want to find some method that is constantly called, so as to check whether the players have won, you can just create a Timer that runs every 1 millisecond. Then the event handler for Timer.Tick would be such a method.
However, you shouldn't find such a method to check for winning/losing. It's a waste of resources to check for that every 1 millisecond.
Think, what action can affect the result of a game of tic tac toe? It's of course when either player places something (X or O) on the board! That is when you need to check whether someone has won. Also, if the thing placed is a X, you don't need to check whether the player who is playing O has won, because that's simply impossible!
Also, checking whether the image in a picture box is equal to the X or O image is really "non abstract" code. Try to put these things into a model by abstraction.
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
I want to make a Kinect program thanks to, when your left hand X position cross your right shoulder X position, it plays the following slide on PowerPoint. I've already done the program part which draws the skeleton stream, and it's work correctly. For the second part, I've tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
bool check = false;
if (leftHand.Position.X == shoulderRight.Position.X && check == false)
{
check = true;
System.Windows.Forms.SendKeys.Send("{RIGHT}");
}
if (leftHand.Position.X == spine.Position.X && check == true)
{
check = false
}
}
Can anyone explain me what is the problem in my code ?
Thanks,
Edit :
I've also tried this :
private void NextSlide(Skeleton skeleton)
{
Joint leftHand = skeleton.Joints[JointType.HandLeft];
Joint spine = skeleton.Joints[JointType.Spine];
Joint shoulderRight = skeleton.Joints[JointType.ShoulderRight];
double lefthandposition = (int)leftHand.Position.X;
double shoulderrightposition = (int)shoulderRight.Position.X;
double spineposition = (int)spine.Position.X;
bool turn = false;
double right = lefthandposition - shoulderrightposition;
bool finish = false;
double ok = lefthandposition - spineposition;
if (right < 0)
{
turn = true;
}
if (ok > 0)
{
finish = true;
}
bool check = false;
if (turn == true && check == false && finish == false)
{
System.Windows.Forms.SendKeys.Send("{RIGHT}");
check = true;
turn = false;
}
if (finish == true && check == true && turn == false)
{
check = false;
finish = false;
}
}
But it doesn't work too :/
The trouble you are running into is that you using == as a check. You will rarely, if ever, run into a situation where two joints are exactly the same value. You need to be using >= or <= for your checks, depending on your needs.
For example, check the JointType.LeftHand >= JointType.RightShoulder, and that JointType.LeftHand <= JointType.Spine, for your position checks.
Another solution could be to use an existing gesture library to accomplish what you want. Here are two of them:
http://kinecttoolbox.codeplex.com/
https://github.com/EvilClosetMonkey/Fizbin.Kinect.Gestures
The Fizbin library's GitHub page explains how to set up and execute on existing gestures: Executing on Gestures. Included in the existing gesture set is a "Swipe Right" and a "Swipe Left" gesture, which execute similar to what you are wanting to do.
The GitHub pages goes into more detail, but a quick rundown would start with setting up the gesture library and a callback:
gestureController = new GestureController();
gestureController.GestureRecognized += OnGestureRecognized;
You'd then initialize the gesture(s) you want to use:
IRelativeGestureSegment[] swipeleftSegments = new IRelativeGestureSegment[3];
swipeleftSegments[0] = new SwipeLeftSegment1();
swipeleftSegments[1] = new SwipeLeftSegment2();
swipeleftSegments[2] = new SwipeLeftSegment3();
gestureController.AddGesture("SwipeLeft", swipeleftSegments);
You can modify the existing gesture components or write your own. The several examples will demonstrate how you can compare joint positions. For example, the first segment in the "SwipeLeft" gesture follows:
public class SwipeLeftSegment1 : IRelativeGestureSegment
{
/// <summary>
/// Checks the gesture.
/// </summary>
/// <param name="skeleton">The skeleton.</param>
/// <returns>GesturePartResult based on if the gesture part has been completed</returns>
public GesturePartResult CheckGesture(Skeleton skeleton)
{
// right hand in front of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.Z < skeleton.Joints[JointType.ElbowRight].Position.Z && skeleton.Joints[JointType.HandLeft].Position.Y < skeleton.Joints[JointType.ShoulderCenter].Position.Y)
{
// right hand below shoulder height but above hip height
if (skeleton.Joints[JointType.HandRight].Position.Y < skeleton.Joints[JointType.Head].Position.Y && skeleton.Joints[JointType.HandRight].Position.Y > skeleton.Joints[JointType.HipCenter].Position.Y)
{
// right hand right of right shoulder
if (skeleton.Joints[JointType.HandRight].Position.X > skeleton.Joints[JointType.ShoulderRight].Position.X)
{
return GesturePartResult.Succeed;
}
return GesturePartResult.Pausing;
}
return GesturePartResult.Fail;
}
return GesturePartResult.Fail;
}
}
Notice it goes through a series of joint checks and returns one of three results:
Succeed: The gesture has completed in full (fired when all the 'if' statements succeed)
Pausing: The gesture is partially complete (fired when you want to indicate the gesture is "in motion" but not complete)
Fail: The gesture is not being executed at all
When you have the gesture you want initialized you just need to send the 'skeleton' data to the gesture library:
private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame == null)
return;
// resize the skeletons array if needed
if (skeletons.Length != frame.SkeletonArrayLength)
skeletons = new Skeleton[frame.SkeletonArrayLength];
// get the skeleton data
frame.CopySkeletonDataTo(skeletons);
foreach (var skeleton in skeletons)
{
// skip the skeleton if it is not being tracked
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
// update the gesture controller
gestureController.UpdateAllGestures(skeleton);
}
}
}
Finally, execute on the gesture:
private void OnGestureRecognized(object sender, GestureEventArgs e)
{
switch (e.GestureName)
{
case "SwipeLeft":
// do what you want to do
break;
default:
break;
}
}