Answered by:
How can I find when the object is rotating to the same direction twice in a row ?
Question

using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateRandom : MonoBehaviour { public string currDirection; bool noTarget = true; Quaternion qTo; float rotateSpeed = 3.0f; float timer = 0.0f; bool directions; float rand; private void Start() { qTo = Quaternion.Euler(new Vector3(0.0f, Random.Range(135.0f, 225.0f), 0.0f)); rand = Random.Range(135.0f, 225.0f); if (rand < 180) { currDirection = "Right"; } if (rand > 180) { currDirection = "Left"; } } private void Update() { timer += Time.deltaTime; if (noTarget == true) { if (timer > 2) { rand = Random.Range(135.0f, 225.0f); if (rand < 180) { currDirection = "Right"; } if (rand > 180) { currDirection = "Left"; } qTo = Quaternion.Euler(new Vector3(0.0f, rand, 0.0f)); timer = 0.0f; } transform.rotation = Quaternion.Slerp(transform.rotation, qTo, Time.deltaTime * rotateSpeed); } } }
This is unity but it's written in c#
The object is rotating randomly between the 135 and 225 degrees.
But now I want to add a rule/s.
If for example the object is rotating to the left twice in a row for example if rand is 185 and then time rand is 200 so that's meaning the object rotated or more stayed on the left side area. In this case I want to pick a random number from the right area.
Same if there are two numbers in a row of the right side so the next time should be picked a random number from the left area.
I tried to use a counter and tried to use two counters one for each direction but can't figure out how to do it.
Update is calling each frame nonstop. So if one of the sides picked randomly twice in a row the next time should be picked randomly from the opposite side.
I tried this but it's not working good, I could count more then two times in a row in one of the sides :
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateRandom : MonoBehaviour { bool noTarget = true; Quaternion qTo; float rotateSpeed = 3.0f; float timer = 0.0f; int sameDirectionCounter = 0; public int maxSameDirection = 2; bool currentDirection = false; // false = left, true = right, would be more elegant to use an enum private void Start() { qTo = Quaternion.Euler(new Vector3(0.0f, Random.Range(135.0f, 225.0f), 0.0f)); } private void Update() { timer += Time.deltaTime; if (noTarget == true) { if (timer > 2) { // to arrive at a range from 90 to 270 (180 degrees) we // take a random range of 0..90, and add or subtract that from // 180. This will then range from 90 to 270. float rand = Random.Range(0.0f, 90.0f); // now flip a coin for left / right bool newDirection = Random.Range(0.f, 1.0f) < 0.5f; // now see if the new direction is the same as the old direction if (newDirection == currentDirection) { // if we are here, this is the same direction as last time // so we need to check how many times this happened already, // and if it happened too many times, force the other direction sameDirectionCounter += 1; if (sameDirectionCounter >= maxSameDirection) { // if we are here, we need to flip the direction newDirection = !newDirection; // flip direction samedirectionCounter = 0; // reset count } } else { samedirectionCounter = 0; } durrentDirection = newDirection; // now calculate the effective turn in degrees float turnAmount = 180.0f; if (newDirection) { // right turnAmount += rand; // add the random value } else { // left turnamount = rand; // subtract the random value } qTo = Quaternion.Euler(new Vector3(0.0f, rand, 0.0f)); timer = 0.0f; } // note that the way you use Slerp here will probably work, but only because you compount two errors :) // because the Slerp value should run from 0..1 (yours will alway be 1/FPS), and because the starting // slerp value should be constant (yours is constantly changing because you are changing transform.rotation) transform.rotation = Quaternion.Slerp(transform.rotation, qTo, Time.deltaTime * rotateSpeed); } } }
I know it's unity but the language is c# and I c an't figure out how to add this rule.
Answers

Greetings Chocolade.
Here's some sample code I hope will help. It has a method that generates a random angle, but won't allow the same direction to be chosen more than twice in a row.
namespace NamespaceX { class Program { static Random random = new Random(); static void Main(string[] args) { for (int i = 0; i < 100; i++) { float rand = NextRandom(); if (rand > 180.0f) Console.WriteLine("Left"); else Console.WriteLine("Right"); } } static float previous = 1.0f; static bool nextIsLeft = false; static bool nextIsRight = false; /// <summary> /// A method to randomly choose a direction, but not allow /// the same direction to be chosen more than twice in a row. /// </summary> /// <returns></returns> static float NextRandom() { float next; if (!(nextIsLeft  nextIsRight)) { next = (float)random.Next(135, 225); } else if (nextIsLeft) { next = (float)random.Next(180, 225); } else { next = (float)random.Next(135, 180); } // If this is the first time through, just return the value. if (previous < 0.0f) { previous = next; return next; } // Set things up ready for the next time through. if (previous <= 180.0f && next <= 180.0f) { // The last two were to the right, so force the next one to the left. nextIsRight = false; nextIsLeft = true; } else if (previous > 180.0f && next > 180.0f) { // The last two to the left, so force the next one to the right. nextIsRight = true; nextIsLeft = false; } else { // The last two were different, so the next one can be anywhere. nextIsRight = false; nextIsLeft = false; } previous = next; return next; } }
 Marked as answer by Chocolade1972 Wednesday, June 26, 2019 4:46 AM

Maybe something like this.
namespace NamespaceX { class Program { static Random random = new Random(); static void Main(string[] args) { for (int i = 0; i < 100; i++) { float rand = NextRandom(); if (IsLeft(rand)) Console.WriteLine("Left"); else Console.WriteLine("Right"); } } static float previous = 1.0f; static bool nextIsLeft = false; static bool nextIsRight = false; static int maxSameDirection = 5; // The maximum number of results in the same direction in a row. static int numberSameDirection = 0; /// <summary> /// A method to randomly choose a direction, but not allow /// the same direction to be chosen more than twice in a row. /// </summary> /// <returns></returns> static float NextRandom() { float next; if (!(nextIsLeft  nextIsRight)) { next = (float)random.Next(135, 225); } else if (nextIsLeft) { next = (float)random.Next(180, 225); } else { next = (float)random.Next(135, 180); } // If this is the first time through, just return the value. if (previous < 0.0f) { previous = next; numberSameDirection = 1; return next; } if (IsLeft(next) == IsLeft(previous)) { numberSameDirection++; if (numberSameDirection >= maxSameDirection) { if (IsLeft(next)) { nextIsLeft = false; nextIsRight = true; } else { nextIsLeft = true; nextIsRight = false; } numberSameDirection = 1; } else { nextIsLeft = false; nextIsRight = false; } } previous = next; return next; } /// <summary> /// Determine if an angle is to left or right. /// </summary> /// <param name="angle"></param> /// <returns></returns> static bool IsLeft(float angle) { return (angle > 180.0f); } }
Edit : I would just like to point out that if the left and right are each 50/50 chances, you are extremely unlikely to get 31 of the same direction in a row. Five or six would be normal, unless the number of tries is in the billions, and even then the normal maximum would probably only be ten or so (my statistics is pretty weak, so someone might correct me). Edited by Ante Meridian Wednesday, June 26, 2019 6:04 AM 31 in a row unlikely.
 Marked as answer by Chocolade1972 Wednesday, June 26, 2019 2:03 PM
All replies

Greetings Chocolade.
Here's some sample code I hope will help. It has a method that generates a random angle, but won't allow the same direction to be chosen more than twice in a row.
namespace NamespaceX { class Program { static Random random = new Random(); static void Main(string[] args) { for (int i = 0; i < 100; i++) { float rand = NextRandom(); if (rand > 180.0f) Console.WriteLine("Left"); else Console.WriteLine("Right"); } } static float previous = 1.0f; static bool nextIsLeft = false; static bool nextIsRight = false; /// <summary> /// A method to randomly choose a direction, but not allow /// the same direction to be chosen more than twice in a row. /// </summary> /// <returns></returns> static float NextRandom() { float next; if (!(nextIsLeft  nextIsRight)) { next = (float)random.Next(135, 225); } else if (nextIsLeft) { next = (float)random.Next(180, 225); } else { next = (float)random.Next(135, 180); } // If this is the first time through, just return the value. if (previous < 0.0f) { previous = next; return next; } // Set things up ready for the next time through. if (previous <= 180.0f && next <= 180.0f) { // The last two were to the right, so force the next one to the left. nextIsRight = false; nextIsLeft = true; } else if (previous > 180.0f && next > 180.0f) { // The last two to the left, so force the next one to the right. nextIsRight = true; nextIsLeft = false; } else { // The last two were different, so the next one can be anywhere. nextIsRight = false; nextIsLeft = false; } previous = next; return next; } }
 Marked as answer by Chocolade1972 Wednesday, June 26, 2019 4:46 AM

This is working great.
One small question. If I want to make it more then twice in a row ? What should I change ? How can I add some global variable that will set the number of times in a row ? For example :
int maxSameDirection = 2;
Or
int maxSameDirection = 31;

Maybe something like this.
namespace NamespaceX { class Program { static Random random = new Random(); static void Main(string[] args) { for (int i = 0; i < 100; i++) { float rand = NextRandom(); if (IsLeft(rand)) Console.WriteLine("Left"); else Console.WriteLine("Right"); } } static float previous = 1.0f; static bool nextIsLeft = false; static bool nextIsRight = false; static int maxSameDirection = 5; // The maximum number of results in the same direction in a row. static int numberSameDirection = 0; /// <summary> /// A method to randomly choose a direction, but not allow /// the same direction to be chosen more than twice in a row. /// </summary> /// <returns></returns> static float NextRandom() { float next; if (!(nextIsLeft  nextIsRight)) { next = (float)random.Next(135, 225); } else if (nextIsLeft) { next = (float)random.Next(180, 225); } else { next = (float)random.Next(135, 180); } // If this is the first time through, just return the value. if (previous < 0.0f) { previous = next; numberSameDirection = 1; return next; } if (IsLeft(next) == IsLeft(previous)) { numberSameDirection++; if (numberSameDirection >= maxSameDirection) { if (IsLeft(next)) { nextIsLeft = false; nextIsRight = true; } else { nextIsLeft = true; nextIsRight = false; } numberSameDirection = 1; } else { nextIsLeft = false; nextIsRight = false; } } previous = next; return next; } /// <summary> /// Determine if an angle is to left or right. /// </summary> /// <param name="angle"></param> /// <returns></returns> static bool IsLeft(float angle) { return (angle > 180.0f); } }
Edit : I would just like to point out that if the left and right are each 50/50 chances, you are extremely unlikely to get 31 of the same direction in a row. Five or six would be normal, unless the number of tries is in the billions, and even then the normal maximum would probably only be ten or so (my statistics is pretty weak, so someone might correct me). Edited by Ante Meridian Wednesday, June 26, 2019 6:04 AM 31 in a row unlikely.
 Marked as answer by Chocolade1972 Wednesday, June 26, 2019 2:03 PM