I am trying to detect if colors are matched (2x2) in Unity2D, but it doesn't fully work. I have 16 tiles with 4 different colors.
I am detecting if the colors are matched with a script, which is attached to each collider which collides with 4 tiles around it. In front of each colider is a button, which rotates the 4 tiles around that button (collider) to the right. The scripts of the colliders have a list called childTiles. The list contains the 4 tiles around that collider, to detect if there are 4 tiles of the same color in one list. It looks like this. (GIF) https://gyazo.com/a2a5c8a5051e937338807fb5ecfaa4ec
This script is attached to each collider. There are 9 colliders in total (each one behind a button).
public GameObject GameManager;
public List<GameObject> ChildTiles = new List<GameObject>();
public GameObject[] ParentPositions;
//public GameObject Tiles;
public bool canTurn = true;
private TileController parentPositions;
private float _rotationDegrees;
private GameManager gameManager;
public Color Green;
public Color Red;
public Color Blue;
public Color Yellow;
public bool greenComplete = false;
public bool redComplete = false;
public bool blueComplete = false;
public bool yellowComplete = false;
public GameObject Topleft; //colliders (only these colliders are necessary out of the 9)
public GameObject Topright;
public GameObject Bottomleft;
public GameObject Bottomright;
public GameObject tileGreen1;
public GameObject tileRed1;
public GameObject tileBlue1;
public GameObject tileYellow1;
void Awake()
{
if (gameObject.name == "Top-left" || gameObject.name == "Top-right" || gameObject.name == "Bottom-left" || gameObject.name == "Bottom-right")
{
Green = tileGreen1.GetComponent<SpriteRenderer> ().color;
Red = tileRed1.GetComponent<SpriteRenderer> ().color;
Blue = tileBlue1.GetComponent<SpriteRenderer> ().color;
Yellow = tileYellow1.GetComponent<SpriteRenderer> ().color;
}
GameManager = GameObject.Find ("GameManager");
//Tiles = GameObject.Find ("Tiles");
ParentPositions = GameObject.FindGameObjectsWithTag ("Position");
}
void Update()
{
greenComplete = parentPositions.greenComplete;
redComplete = parentPositions.redComplete;
blueComplete = parentPositions.blueComplete;
yellowComplete = parentPositions.yellowComplete;
}
void Start()
{
gameManager = GameManager.GetComponent<GameManager> ();
_rotationDegrees = 0f;
foreach (GameObject go in ParentPositions)
{
parentPositions = go.GetComponent<TileController> ();
}
}
public void SquareClicked()
{
if (parentPositions.canTurn == true && gameManager.turns > 0f)
{
gameManager.turns -= 1;
gameManager.turnsText.text = "Turns: " + gameManager.turns;
foreach(GameObject go in ParentPositions)
{
parentPositions = go.GetComponent<TileController> ();
parentPositions.canTurn = false;
}
foreach(GameObject tile in ChildTiles)
{
tile.transform.parent = gameObject.transform;
}
StartCoroutine(Rotate()); //this is where you do the rotation of the parent object.
if (gameManager.turns == 0f)
{
gameManager.turnsText.text = "No turns left";
}
}
}
IEnumerator Rotate()
{
LeanTween.rotateZ (gameObject, _rotationDegrees - 90f, 0.5f);
_rotationDegrees -= 90f;
if (_rotationDegrees == -360f)
{
_rotationDegrees = 0f;
}
yield return new WaitForSeconds (0.5f);
parentPositions.canTurn = true;
yield return new WaitForSeconds (0.5f);
if (parentPositions.greenComplete == false)
{
parentPositions.greenComplete = parentPositions.ChildTiles.All (t => t.GetComponent<SpriteRenderer> ().color == Green);
}
if (parentPositions.redComplete == false)
{
parentPositions.redComplete = parentPositions.ChildTiles.All (t => t.GetComponent<SpriteRenderer> ().color == Red);
}
if (parentPositions.blueComplete == false)
{
parentPositions.blueComplete = parentPositions.ChildTiles.All (t => t.GetComponent<SpriteRenderer> ().color == Blue);
}
if (parentPositions.yellowComplete == false)
{
parentPositions.yellowComplete = parentPositions.ChildTiles.All (t => t.GetComponent<SpriteRenderer> ().color == Yellow);
}
Debug.Log ("_greenComplete " + parentPositions.greenComplete);
Debug.Log ("_redComplete " + parentPositions.redComplete);
Debug.Log ("_blueComplete " + parentPositions.blueComplete);
Debug.Log ("_yellowComplete " + parentPositions.yellowComplete);
if (parentPositions.greenComplete && parentPositions.redComplete && parentPositions.blueComplete && parentPositions.yellowComplete)
{
Debug.Log ("Level Complete");
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Tile")
{
ChildTiles.Add (col.gameObject);
}
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "Tile")
{
ChildTiles.Remove (col.gameObject);
}
}
As you can see in the GIF, there is a problem. The problem is that when there are 4 colors matched, it doesn't return True. It only returns True if you click a button with 4 tiles of the same color around it. Only then it returns True. So you match 4 colors, it doesn't return True, you click the button with those 4 colors around it, it returns True. How do I make it so that it immediately returns True, if 4 colors are matched? As you can see I only use the top-left, top-right, bottom-left and bottom-right collider, as these are the only possible colliders to have 4 tiles with the same color in them at the same time.
Related
I have a 3D board game in Unity. I would like to move my character without having to press a key, but most importantly I would like to show a dynamic panel in canvas for whatever square the character lands on. So far I have the dice rolling and the character moving (after pressing a key) the correct amount of squares, but I am unable to figure out how to activate the panel based on the square color. Any help would be appreciated.
Here is my CharacterScript:
public class CharacterScript : MonoBehaviour
{
public Path currentPath;
public int squarePosition;
public int squares;
bool isMoving;
public GameObject PinkSquarePanel = GameObject.FindGameObjectWithTag("PinkSquare");
public GameObject CyanSquarePanel = GameObject.FindGameObjectWithTag("CyanSquare");
public GameObject WhiteSquarePanel = GameObject.FindGameObjectWithTag("WhiteSquare");
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape) && !isMoving)
{
squares = DiceNumberTextScript.diceNumber;
}
StartCoroutine(Move());
if (squares == 0)
{
ActivateSquarePanel();
}
}
IEnumerator Move()
{
if (isMoving)
{
yield break;
}
isMoving = true;
while (squares > 0)
{
Vector3 nextPosition = currentPath.squareList[squarePosition + 1].position;
while (MoveToNextSquare(nextPosition))
{
yield return null;
}
yield return new WaitForSeconds(0.1f);
squares--;
squarePosition++;
}
isMoving = false;
}
bool MoveToNextSquare(Vector3 goal)
{
return goal != (transform.position = Vector3.MoveTowards(transform.position, goal, 4f * Time.deltaTime));
}
void ActivateSquarePanel()
{
if (squarePosition.Equals(PinkSquarePanel))
{
PinkSquarePanel.GetComponent<CanvasGroup>().alpha = 1;
}
else if (squarePosition.Equals(CyanSquarePanel))
{
CyanSquarePanel.GetComponent<CanvasGroup>().alpha = 1;
}
else if (squarePosition.Equals(WhiteSquarePanel))
{
WhiteSquarePanel.GetComponent<CanvasGroup>().alpha = 1;
}
}
}
And here is my PathScript:
public class Path : MonoBehaviour
{
Transform[] squareObjects;
public List<Transform> squareList = new List<Transform>();
GameObject[] PinkSquares = GameObject.FindGameObjectsWithTag("PinkSquare");
PinkSquare[] pinkList = new PinkSquare[1];
GameObject[] CyanSquares = GameObject.FindGameObjectsWithTag("CyanSquare");
CyanSquare[] cyanList = new CyanSquare[1];
GameObject[] WhiteSquares = GameObject.FindGameObjectsWithTag("WhiteSquare");
WhiteSquare[] whiteList = new WhiteSquare[1];
private void OnDrawGizmos()
{
Gizmos.color = Color.black;
FillSquares();
for (int i = 0; i < squareList.Count; i++)
{
Vector3 currentPosition = squareList[i].position;
if (i > 0)
{
Vector3 previousPosition = squareList[i - 1].position;
Gizmos.DrawLine(previousPosition, currentPosition);
if(currentPosition.Equals(PinkSquares))
{
pinkList[i] = new PinkSquare();
}
else if (currentPosition.Equals(CyanSquares))
{
cyanList[i] = new CyanSquare();
}
else if (currentPosition.Equals(WhiteSquares))
{
whiteList[i] = new WhiteSquare();
}
}
}
}
void FillSquares()
{
squareList.Clear();
squareObjects = GetComponentsInChildren<Transform>();
foreach (Transform square in squareObjects)
{
if (square != this.transform)
{
squareList.Add(square);
}
}
}
}
I believe your issue is in your comparisons, you are trying to use an Equals to compare your currentPosition which is a Vector3 type to a GameObject[] which is an array of gameObjects. As I mentioned in my comments, this comparison will always fail as an array of gameObjects can not be equal to a vector.
Instead of using these lines, try this line:
if(squareList[i].gameObject.tag.CompareTag("PinkSquare")
The full snippet of if else would look like
if(squareList[i].gameObject.tag.CompareTag("PinkSquare")
{
pinkList[i] = new PinkSquare();
}
else if(squareList[i].gameObject.tag.CompareTag("CyanSquare")
{
cyanList[i] = new CyanSquare();
}
else if(squareList[i].gameObject.tag.CompareTag("WhiteSquare")
{
whiteList[i] = new WhiteSquare();
}
Your CharacterScript is going to need to get the gameObject or Transform from the Path script as it is only keeping track of indexes. Your issue in this script is you are comparing an integer to a GameObject which would never be true. I would also recommend not using OnDrawGizmos() as it is an editor only script and should only be used to render editor debugging tools. The only reference to a Gizmo I see in the function is Gizmos.color = Color.black; which does nothing as you are not rendering a gizmo anywhere. I would move this code to a different function and call it from your CharacterScript. Have the return type be GameObject or Transform of the square you are on, so the CharacterSCript can check which color it lands on. Using an Integer nor Vector3 to compare to a GameObject[] will never work.
I am not sure if there are issues elsewhere in the code, but as this comparison would always fail, none of these statements would get broken into. What this means is your panels would never have the chance to get their alpha set nor get created.
Suppose maximum brightness of an item is 100% and vice versa. When I glance at one of them, the item should be gradually brightening up from 0% to 100%. So when I look away halfway of the brightening, the object will slowly dim back to 0%. When I glance back again, the brightening will just resume. I am using Color.Lerp for my brightening and dimming back down.
Each item has their own individual pace of brightening and dimming back down even when they are gathered in a very tight space.
Assume that Item A, B, C, D and E arranged tightly beside each other in order. Hence, I glance at Item A which its brightness has reached to 80% and I immediately shift through B,C and D then stop and glance at E to reach its maximum brightness. In this scenario, A should be dimming back down, while B, C and D brightens up a little bit. Then E will be brightening to the max. How do I achieve this no matter how many items I have on the spot? I am having problem with updating the info of current item and keeping the info of previous item.
The code works well on a single item AND ALSO glancing back and forth between two items. But when there are three or more objects involved, the codes just doesn't work anymore.
Scripts are as below:
Raycast to detect items
public class RaycastSelection : MonoBehaviour
{
RaycastHit hit;
Ray ray;
public GameObject currentObject;
public GameObject previousObject;
public GameObject lastPreviousObject;
public GameObject lastObject;
private bool saveObjectOnce = false;
private bool isFading = false;
private bool fadeOnce = false;
private ColorFade colorFading;
private ColorFade colorFading1;
private ColorFade colorFading2;
public void Start()
{
colorFading = GameObject.FindWithTag("Puzzle").GetComponent<ColorFade>();
colorFading1 = GameObject.FindWithTag("Clue").GetComponent<ColorFade>();
colorFading2 = GameObject.FindWithTag("Selectable").GetComponent<ColorFade>();
}
public void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 forward = Camera.main.transform.TransformDirection(Vector3.forward) * 10;
Debug.DrawRay(Camera.main.transform.position, forward, Color.red);
//if player is looking
if (Physics.Raycast(ray, out hit))
{
var selection = hit.transform;
if (selection.CompareTag("Puzzle") || selection.CompareTag("Clue") || selection.CompareTag("Selectable"))
{
//if it is first time looking at object
if(currentObject == null)
{
currentObject = hit.transform.gameObject;
}
//if it is second time looking at object
else
{
if (saveObjectOnce == false)
{
previousObject = currentObject;
saveObjectOnce = true;
}
currentObject = hit.transform.gameObject;
}
//if previous and current object are same
if(string.Equals(currentObject, previousObject))
{
isFading = true;
ColorFade fadingColor = currentObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
if (lastPreviousObject != null)
{
isFading = false;
ColorFade fadingcolor = lastPreviousObject.GetComponent<ColorFade>();
fadingcolor.FadeCheck(isFading);
}
}
//if previous and current object are different
else
{
lastPreviousObject = previousObject;
previousObject = currentObject;
}
}
//if detects other objects than the items
else
{
lastObject = currentObject;
isFading = false;
if (lastObject != null)
{
ColorFade fadingColor = lastObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
}
}
}
//if the player is not looking
else
{
lastObject = currentObject;
if (lastObject != null)
{
ColorFade fadingColor = lastObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
}
}
}
}
Changing brightness of the item (This script is attached to each item individually)
public class ColorFade : MonoBehaviour
{
[SerializeField] private bool saveColorOnce = false;
[SerializeField] private Transform thisObject;
[SerializeField] private Color startColor;
[SerializeField] private Color EndColor;
[SerializeField] private float lerpFadeTime = 0f;
private void Start()
{
startColor = this.transform.GetComponent<Renderer>().material.color;
thisObject = this.transform;
}
public void Update()
{
}
public void FadeCheck(bool fadingStatus)
{
if(fadingStatus == true)
{
FadeIn();
}
else
{
FadeOut();
}
}
private void FadeIn()
{
Debug.Log(this.transform.gameObject.name);
Debug.Log("FadeIn");
lerpFadeTime += Time.deltaTime / 3f;
thisObject.GetComponent<Renderer>().material.color = Color.Lerp(startColor, EndColor, lerpFadeTime);
if(lerpFadeTime >= 1f)
{
lerpFadeTime = 1f;
}
}
private void FadeOut()
{
Debug.Log(this.transform.gameObject.name);
Debug.Log("FadeOut");
lerpFadeTime -= Time.deltaTime / 3f;
thisObject.GetComponent<Renderer>().material.color = Color.Lerp(startColor, EndColor, lerpFadeTime);
if (lerpFadeTime <= 0f)
{
lerpFadeTime = 0f;
}
}
}
I would suggest Coroutines which are most of the times better to control than using complex Update methods with timers, states and bools.
public class RaycastSelection : MonoBehaviour
{
[Header("Components")]
// reference this via the Inspector already if possible
[SerializeField] private Camera camera;
[Header("Debug")]
[SerializeField] private ColorFade lastFaderHit;
private void Awake()
{
if (!camera) camera = Camera.main;
}
private void Update()
{
RaycastHit hit;
if (Physics.Raycast(camera.ScreenPointToRay(Input.mousePosition), out hit))
{
// if hitting same object do nothing
if (lastFaderHit && hit.transform == lastFaderHit.transform) return;
// if looking on different object start fade out previous if exists
lastFaderHit?.FadeOut();
// start fade in current
var current = hit.transform.GetComponent<ColorFade>();
current?.FadeIn();
// update previous hit
lastFaderHit = current;
}
else
{
// if looking at nothing start fadeout previous hit if exists
lastFaderHit?.FadeOut();
// reset previous hit
lastFaderHit = null;
}
}
}
and in ColorFade use coroutines like
public class ColorFade : MonoBehaviour
{
[Header("Components")]
// reference this in the Inspector if possible
[SerializeField] private Renderer renderer;
[Header("Settings")]
[SerializeField] private Color startColor;
[SerializeField] private Color EndColor;
// fade duration for a complete 0-100 fade
// fading will be shorter if only fading parts
[SerializeField] private float fadeDuration = 1f;
[Header("Debug")]
[SerializeField] [Range(0f, 1f)] private float currentFade;
private void Awake()
{
if (!renderer) renderer = GetComponent<Renderer>();
startColor = renderer.material.color;
}
public void FadeIn()
{
// avoid concurrent routines
StopAllCoroutines();
StartCoroutine(FadeTowards(1));
}
public void FadeOut()
{
// avoid concurrent routines
StopAllCoroutines();
StartCoroutine(FadeTowards(0));
}
private IEnumerator FadeTowards(float targetFade)
{
while (!Mathf.Approximately(currentFade, targetFade))
{
// increase or decrease the currentFade according to the fade speed
if (currentFade < targetFade)
currentFade += Time.deltaTime / fadeDuration;
else
currentFade -= Time.deltaTime / fadeDuration;
// if you like you could even add some ease-in and ease-out here
//var lerpFactor = Mathf.SmoothStep(0, 1, currentFade);
renderer.material.color = Color.Lerp(startColor, EndColor, currentFade /*or lerpFactor for eased fading*/);
// let this frame be rendered and continue from this point
// in the next frame
yield return null;
}
}
}
Fade an object out if it's not currently being viewed
Don't worry about which objects are fading out and not selected. That is the job of the fader. If it's not being viewed, it's fading out. It's that simple.
Fader.cs - Put this component on your objects that can be faded
public class Fader : MonoBehaiour
{
// Flag to know if the object is currently being viewed
public bool IsCurrentlyViewed = false;
// Time in seconds it takes to fade from 100% brightness to 0% brightness. Default is 3 seconds
[SerializeField] private float SecondsTimeToFade = 3.0f;
// Ratio from 0 to 1 to indicate how bright an object should be
[SerializeField] private float PercentRatioBright = 0.0f;
// Start and end colors
[SerializeField] private Color startingColor;
[SerializeField] private Color endingColor;
// Cache the renderer
private Renderer renderer;
public void Start()
{
renderer = GetComponent<Renderer>();
startingColor = renderer.material.color;
if (layer < 8)
Debug.LogWarning("Fader layer should be set to a player-defined layer");
}
public void Update()
{
// Fade in when being viewed, fade out when not
if (PercentRatioBright > 0.0f && PercentRatioBright <= 1.0f)
Fade();
// Reset the IsCurrentlyViewed bool
IsCurrentlyViewed = false;
}
private void Fade()
{
float brightnessRatioUnsignedDifference = Time.deltaTime / SecondsTimeToFade;
PercentRatioBright += brightnessRatioUnsignedDifference * (IsCurrentlyViewed ? 1 : -1);
renderer.material.color = Color.Lerp(startingColor, endingColor, PercentRatioBright);
}
}
Example call:
public class ThroughTheLookingClass : MonoBehaiour
{
// Set this so you only hit what you want with the ray
// Make sure your selectable objects have this layer
[SerializeField] private LayerMask SelectableLayerMask;
public Update()
{
// Cast screen point to ray, select objects with layermask and have the Fader component
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition, out RaycastHit hit, layerMask: SelectableLayerMask)))
{
hit.transform.gameObject.GetComponent<Fader>()?.IsCurrentlyViewed = true;
}
}
}
I revisit my own script and made some changes, so the code works out fine now.
RaycastHit hit;
Ray ray;
public GameObject nextObject;
public GameObject currentObject;
public GameObject previousObject;
public GameObject lastPreviousObject;
public GameObject lastObject;
private bool saveObjectOnce = false;
private bool isFading = false;
private bool fadeOnce = false;
public void Start()
{
}
public void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 forward = Camera.main.transform.TransformDirection(Vector3.forward) * 10;
Debug.DrawRay(Camera.main.transform.position, forward, Color.red);
//if player is looking
if (Physics.Raycast(ray, out hit))
{
var selection = hit.transform;
if (selection.CompareTag("Puzzle") || selection.CompareTag("Clue") || selection.CompareTag("Selectable"))
{
nextObject = selection.gameObject;
//if previous and current object are same
if (GameObject.Equals(nextObject, currentObject))
{
isFading = true;
ColorFade fadingColor = currentObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
if(previousObject != null)
{
isFading = false;
ColorFade fadingcolor1 = previousObject.GetComponent<ColorFade>();
fadingcolor1.FadeCheck(isFading);
}
if(GameObject.Equals(currentObject, lastPreviousObject))
{
lastPreviousObject = null;
}
else {
if (lastPreviousObject != null)
{
isFading = false;
ColorFade fadingcolor = lastPreviousObject.GetComponent<ColorFade>();
fadingcolor.FadeCheck(isFading);
}
}
}
//if previous and current object are different
else
{
lastPreviousObject = previousObject;
previousObject = currentObject;
currentObject = nextObject;
}
}
//if detects other objects than the items
else
{
isFading = false;
lastObject = nextObject;
if (lastObject != null)
{
ColorFade fadingColor = lastObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
}
}
}
//if the player is not looking
else
{
isFading = false;
lastObject = nextObject;
if (lastObject != null)
{
ColorFade fadingColor = lastObject.GetComponent<ColorFade>();
fadingColor.FadeCheck(isFading);
}
}
As you can see, I started with an object in a scene and attached a script to it along with other components. https://imgur.com/z9Tooh9
It looks barren due to there not actually being a model in there. However, when the game is started, it is created by another script in an object in the hierarchy. https://imgur.com/guQQlJO
You can also see that the script works as expected and detects all the skinned mesh renderers and allows you to adjust the colors accordingly.
However, this is where the problem comes in.
When I duplicate this object the first object does what is expected of it but, the second one doesn't.
As you can see, there are no skinned mesh renderers in the list for the second object. https://imgur.com/zTRHL9F
Naturally, I put debug logs at the point where it detects the skinned mesh renderers to see what the issue is:
void OnMouseEnter()
{
Debug.Log("Mouse Entered");
foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For
every object it finds
{
Debug.Log("Detected: " + element);
Debug.Log("Detected Color: " + selectedColor);
element.material.color = selectedColor;
}
}
void OnMouseExit()
{
Debug.Log("Mouse Left");
foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For
every object it finds
{
//Debug.Log("Detected: " + element);
//Debug.Log("Detected Color: " + deselectedColor);
element.material.color = deselectedColor;
}
}
The first object notes that they're detected. https://imgur.com/fBhXjKj
The second one simply pretends as if the debug log is not even there. https://imgur.com/alE76aY
I'm more than happy to elaborate in the event that you don't quite understand what it is I'm asking.
Many thanks in advance and sorry if my formatting is terrible I'm not the best at it.
I've tried searching for answers online but, I could not locate a solution to my rather unique problem.
The whole script is as follows:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankController : MonoBehaviour
{
Vector3 targetPosition;
Vector3 lookAtTarget;
public Vector4 selectedColor;
public Vector4 deselectedColor;
Quaternion playerRot;
float rotSpeed = 2;
float speed = 3;
bool moving = false;
public bool Building = false;
public bool selected = false;
public bool CoolingDown = false;
public double CoolDown = .2;
public double original = .2;
MeshRenderer RenderMesh;
MeshRenderer RenderMeshParent;
SkinnedMeshRenderer[] skinnedMeshRenderersScan;
public List<SkinnedMeshRenderer> skinnedMeshRenderersList = new
List<SkinnedMeshRenderer>();
// Use this for initialization
void Start()
{
RenderMesh = GetComponentInChildren<MeshRenderer>();
RenderMeshParent = GetComponentInParent<MeshRenderer>();
skinnedMeshRenderersScan = GetComponentsInChildren<SkinnedMeshRenderer> ();
foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
{
if (!skinnedMeshRenderersList.Contains(element)) //If it isn't already in this list
{
skinnedMeshRenderersList.Add(element); //Add to the list
}
}
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
if (CoolingDown == false) //If not cooling down
{
SetTargetPosition();
CoolingDown = true; //Set cooling down to true
}
}
if (CoolingDown == true)
{
CoolDown -= Time.deltaTime; //Takes some time away
if (CoolDown <= 0) //Checks if the cooldown is done yet
{
CoolingDown = false; //Sets cooling down to false
CoolDown = original; //Cooldown timer is reset by equalling its original value
}
}
if (moving)
Move();
}
void SetTargetPosition()
{
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
if (hit.collider.CompareTag("Hittable") == true && selected == true)
{
targetPosition = hit.point;
lookAtTarget = new Vector3(targetPosition.x - transform.position.x,
transform.position.y,
targetPosition.z - transform.position.z);
playerRot = Quaternion.LookRotation(lookAtTarget);
moving = true;
}
if (hit.collider.CompareTag("Unit") == true)
{
Fighting self = GetComponentInChildren<Fighting>();
Fighting other = hit.collider.gameObject.GetComponentInChildren<Fighting>();
PlayerMaster playcheck = GetComponent<PlayerMaster>();
if (CoolingDown == false) //If not cooling down
{
if (gameObject.name == hit.collider.name)
{
if (selected == false)
{
selected = true;
RenderMesh.enabled = !RenderMesh.enabled;
}
else if (selected == true)
{
selected = false;
RenderMesh.enabled = !RenderMesh.enabled;
}
}
CoolingDown = true; //Set cooling down to true
}
}
}
}
}
void Move()
{
if (Building == false)
{
transform.rotation = Quaternion.Slerp(transform.rotation,
playerRot,
rotSpeed * Time.deltaTime);
transform.position = Vector3.MoveTowards(transform.position,
targetPosition,
speed * Time.deltaTime);
if (transform.position == targetPosition)
moving = false;
}
}
void OnMouseEnter()
{
Debug.Log("Mouse Entered");
foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
{
Debug.Log("Detected: " + element);
Debug.Log("Detected Color: " + selectedColor);
element.material.color = selectedColor;
}
}
void OnMouseExit()
{
Debug.Log("Mouse Left");
foreach (SkinnedMeshRenderer element in skinnedMeshRenderersScan) //For every object it finds
{
//Debug.Log("Detected: " + element);
//Debug.Log("Detected Color: " + deselectedColor);
element.material.color = deselectedColor;
}
}
}
To recap, the expected result is that the second object (Or more) would work the same way the first object does.
In practice, it does not.
I was able to fix this issue by putting the scans in the awake() method.
I have several objects with the same tag, and I want to check if they are moving or not, to call a function when they're not moving. So I used the code bellow, but the aremoving is always false even when some objects still moving! Do you know what's wrong in my code?
Script:
bool aremoving;
void LateUpdate()
{
GameObject[] Cubes = GameObject.FindGameObjectsWithTag("Cube");
foreach (GameObject Cube in Cubes)
{
if (Cube.GetComponent<Rigidbody>() == null)
{
continue;
}
if (Cube.GetComponent<Rigidbody>().velocity.magnitude > 0.01)
{
aremoving = true;
}
if (Cube.GetComponent<Rigidbody>().velocity.magnitude <= 0.01)
{
aremoving = false;
}
}
Debug.Log("Cubes moving: " + aremoving);
}
Write the code like this
bool aremoving;
void LateUpdate()
{
GameObject[] Cubes = GameObject.FindGameObjectsWithTag("Cube");
foreach (GameObject Cube in Cubes)
{
if (Cube.GetComponent<Rigidbody>() == null)
{
continue;
}
if (Cube.GetComponent<Rigidbody>().velocity.magnitude > 0.01f)
{
aremoving = true;
}
Debug.Log("Cubes moving: " + aremoving);
aremoving = false;
}
I want my Player to collide with the object capsule.
This action should destroy the capsule and add a speed value of 10 to the player.
But this code is not working :
public class PlayerController : MonoBehaviour {
public KeyCode moveL;
public KeyCode moveR;
public float horizontal = 0;
public int laneNum = 2;
public string controllocked = "n";
public float speed;
void Update ()
{
GetComponent<Rigidbody>().velocity = new Vector3(horizontal, GM.verticalVelocity, speed);
if ((Input.GetKeyDown(moveL)) && (laneNum > 1) && (controllocked == "n"))
{
horizontal = -2;
StartCoroutine(StopSlide());
laneNum = laneNum - 1;
controllocked = "y";
}
else if ((Input.GetKeyDown(moveR)) && (laneNum < 3) && (controllocked =="n"))
{
horizontal = 2;
laneNum = laneNum + 1;
StartCoroutine(StopSlide());
controllocked = "y";
}
}
void OnCollisionEnter(Collision other)
{
if(other.gameObject.tag == "lethal")
{
Destroy(gameObject);
}
if (other.gameObject.name == "Capsule")
{
Destroy(other.gameObject);
speed = 10;
}
}
IEnumerator StopSlide()
{
yield return new WaitForSeconds(.5f);
horizontal = 0;
controllocked = "n";
}
What I've tried so far is speed += 10 and speed++ neither works.
Well, at first try to check your player, What collider type that you use in the player?
Make sure you check trigger in the collider component and add rigidbody into it.
The capsule object must have rigidbody on it.
Hope it help.
Use OnTriggerEnter(Collider collider) if you want to use triggerenter. Collision enter work if trigger is not checked