So I have got two scene change scripts, both which are attached to two different game objects. But for some reason, one script affects both game objects. So I am trying to temporarily disable one of the scripts when the other script is active on the other game object. Here is what I have but this is returning the error, "BasketballSceneChange' is a type, which is not valid in the given context".
**GameObject.Find("pPrism1").GetComponent(BasketballSceneChange).enabled = false;**
{
if (Input.GetMouseButtonDown(0) && SceneManager.GetActiveScene().name == "MWalk")
{
SceneManager.LoadScene("BWalk");
}
if (Input.GetMouseButton(0) && SceneManager.GetActiveScene().name == "BWalk")
{
SceneManager.LoadScene("Basketball");
}
if (Input.GetMouseButton(0) && SceneManager.GetActiveScene().name == "Football")
{
SceneManager.LoadScene("SWalk");
}
if (Input.GetMouseButton(0) && SceneManager.GetActiveScene().name == "SWalk")
{
SceneManager.LoadScene("MWalk");
}
}
}
Change this:
GameObject.Find("pPrism1").GetComponent(BasketballSceneChange).enabled = false;
to
var myVariable = GetComponent(BasketballSceneChange) as myBaseClass;
myVariable.enabled = false;
change myBaseClass to class which shows your Scene.
You could avoid using GetComponent just declaring a public variable and assigning it from the inspector.
public AnotherScript theOtherScript;
void Update()
{
if(theOtherScript != null && theOtherScript.enabled)
{
theOtherScript.enabled = false;
}
}
Check this Tutorial
Other way is Finding the gameobject and geting the component as you did.
I've read your code again and I found the error that doesn't compile the line:
GameObject.Find("pPrism1").GetComponent(BasketballSceneChange).enabled = false;
should be
GameObject.Find("pPrism1").GetComponent<BasketballSceneChange>().enabled = false;
Related
I'm developing a search game, where players must look for certain objects. Whenever the targeted object is found and has been picked up, the player wins and go to the next level. I tagged the targeted objects as "TargetObj". I successfully implemented this when there is only one object to look for. I want to modify my code to include cases where there is more than one object to look for. Here is my code :
public void someFunction() {
//if we press the button of choice
if (Input.GetKeyDown(KeyCode.Space)) {
//and we're not holding anything
if (currentlyPickedUpObject == null) {
//and we are looking an interactable object
if (lookObject != null) {
PickUpObject();
}
} else { //if we press the pickup button and have something, we drop it
BreakConnection();
}
}
}
/* ommitted lines */
public void PickUpObject() {
if (GameObject.FindGameObjectsWithTag("TargetObj").Length == 1 & lookObject.tag == "TargetObj") {
physicsObject = lookObject.GetComponentInChildren<PhysicsObjects>();
currentlyPickedUpObject = lookObject;
pickupRB = currentlyPickedUpObject.GetComponent<Rigidbody>();
pickupRB.constraints = RigidbodyConstraints.FreezeRotation;
physicsObject.playerInteractions = this;
winUI.SetActive(true);
Time.timeScale = 0f;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
Time.timeScale = 1f;
} else if (GameObject.FindGameObjectsWithTag("TargetObj").Length > 1) {
} else {
physicsObject = lookObject.GetComponentInChildren<PhysicsObjects>();
currentlyPickedUpObject = lookObject;
pickupRB = currentlyPickedUpObject.GetComponent<Rigidbody>();
pickupRB.constraints = RigidbodyConstraints.FreezeRotation;
physicsObject.playerInteractions = this;
}
}
I added this line, to check if there is more than one object to look for.
else if (GameObject.FindGameObjectsWithTag("TargetObj").Length > 1)
How to implement this (if the player picked up all objects of tag "TargetObj", go to next level.)?
A fast way of doing this is to keep a counter of picked objects. Then, if the counter is equal with the number of objects with the "TargetObj" tag, then the player wins. As snippet you can have something like this:
Gameobject[] targetObjects; // an array where you will keep your objects with "TargetObj" tag
List<GameObject> targetObjectsList;
void Start()
{
targetObjects = GameObject.FindGameObjectsWithTag("TargetObj");
targetObjectsList = new List<GameObject>();
}
.
.
.
// In your method (You didn't put all your code so I will use your snippet)
if (Input.GetKeyDown(KeyCode.Space))
{
//and we're not holding anything
if (currentlyPickedUpObject == null)
{
//and we are looking an interactable object
if (lookObject != null )
{
PickUpObject();
// I suppose that "lookObject" is the gameobject that you want to pickup. If not, replase this variable with the right gameobject.
if(!targetObjectsList.Contains(lookObject.gameObject))
{
targetObjectsList.Add(lookObject.gameObject);
if (targetObjectsList.Count == targetObjects.Length)
{
//Finish the game
winUI.SetActive(true);
Time.timeScale = 0f;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
Time.timeScale = 1f;
}
}
}
}
}
//if we press the pickup button and have something, we drop it
else
{
BreakConnection();
}
}
Then you modify your PickUpObject method, just to pick and drop objects.
I'm sorry if I miss something. I wrote this without an editor and I didn't test the code, so please tell me if is something that I miss.
I attached the following script to a GameObject to determine if it is a mesh.
using UnityEngine;
public class MeshCheck : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var meshChecker = this.GetComponent<MeshRenderer>();
if(meshChecker != null)
{
Debug.Log("this is mesh");
}
else
{
Debug.Log("this is not mesh");
}
}
}
This script seems to work fine as far as I've tried.
However, this method does not seem to be able to determine all meshes.
For example, there is a mesh with a blendShapeds.I opened and looked at the Inspector for that mesh. It seemed that the the mesh have "SkinMeshRenderer" and the mesh didn't have "MeshRenderer". And the above script output "this is not mesh".
The solution to this problem is to modify the script as follows:
using UnityEngine;
public class MeshCheck : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var meshChecker = this.GetComponent<MeshRenderer>();
var blendShapeChecker = this.GetComponent<SkinnedMeshRenderer>();
if (meshChecker != null || blendShapeChecker != null)
{
Debug.Log("this is mesh");
}
else
{
Debug.Log("this is not mesh");
}
}
}
I'm wondering if the second script solves all the problems.
If anyone knows how to accurately determine all meshes, please let me know.
You can use the Mesh Filter to avoid having all the controls via code.
In this way instead of having
if (meshChecker != null || blendShapeChecker != null || othermeshes...)
You will check
if(MeshFilter.mesh != null)
But with the Mesh Filter you can play with multiple meshes and check between all of them with the Mesh.SubMeshCount or the Mesh.setIndices or even Mesh.CombineMeshes but it's all about the usage you need for the game!
I have created a scene which changes scenes to a vuforia scene where I can scan objects, from this scene I want to change to a different scene depending on the name[or through some sort of unique identification] of the scanned scene after an image target is found as I have more than one images which should display different information after getting scanned.
I implemented the code in a trackableEventHandler that overrides the default one, and added the code in the OnTrackableStateChanged(). I defined a Transform called Transform and I'm using this to get the name so I can change scenes with it. I followed an example and transform was used. Any different suggestion is fine.
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus){
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED){
Debug.Log("Image Found");
}
else{
Debug.Log("Image lost!");
}
//
StateManager stateManager = TrackerManager.Instance.GetStateManager();
IEnumerable<TrackableBehaviour> trackableBehaviours = stateManager.GetActiveTrackableBehaviours();
foreach (TrackableBehaviour trackableBehaviour in trackableBehaviours)
{
string scanName = trackableBehaviour.TrackableName;
Transform.GetComponent<Text>().text = scanName;
if(scanName == "scannedImage")
{
SceneManager.LoadScene("ScannedImageScene");
}
else if(scanName == "otherImage")
{
SceneManager.LoadScene("OtherImageScene");
}
}
}
Below is my code. I've connected hearts one - three to sprites that should hide when the player is hit but only heart three works.
what do I need to change so it works for all three hearts?
public class HealthManagement : MonoBehaviour {
public Transform heartOne;
public Transform heartTwo;
public Transform heartThree;
// Use this for initialization
void Start()
{
heartOne.gameObject.SetActive(true);
heartTwo.gameObject.SetActive(true);
heartThree.gameObject.SetActive(true);
}
// Update is called once per frame
void Update() { }
void OnTriggerEnter2D(Collider2D player)
{
if (player.gameObject.CompareTag("Enemy") && heartThree.gameObject == true)
{
heartThree.gameObject.SetActive(false);
Debug.Log("3");
}
if (player.gameObject.CompareTag("Enemy") && heartThree.gameObject == false && heartTwo.gameObject == true )
{
heartTwo.gameObject.SetActive(false);
Debug.Log("2");
}
if (player.gameObject.CompareTag("Enemy") && heartThree.gameObject == false && heartTwo.gameObject == false && heartOne.gameObject == true)
{
heartOne.gameObject.SetActive(false);
Debug.Log("1");
}
}
}
I think it might be the heartThree.gameObject == true part.
From the Unity docs:
bool Does the object exist?
So heartThree.gameObject == false will never trigger.... the objects DO exist but are inactive.
Maybe try with heartThree.gameObject.activeSelf == false to check for the active state
You can use the framework https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 from AssetStore for a beautiful animation without using a down timer. )))
So below you will find a short snippet of code. What this code does is it allows the player to hit the 'p' key to pause the game and when this happens a gui pops up and the players look and movement controls are disabled. My problem is with deactivating and reactivating the gui because it is a game object. It lets me deactivate it but when I try to activate it I get an error.
Code:
UnityEngine.Component walkScriptOld = GameObject.FindWithTag ("Player").GetComponent ("CharacterMotor");
UnityEngine.Behaviour walkScript = (UnityEngine.Behaviour)walkScriptOld;
UnityEngine.GameObject guiMenu = GameObject.FindWithTag ("Canvas");
if ((Input.GetKey ("p")) && (stoppedMovement == true)) {
stoppedMovement = false;
walkScript.enabled = true;
guiMenu.SetActive(true);
} else if ((Input.GetKey ("p")) && (stoppedMovement == false)) {
stoppedMovement = true;
walkScript.enabled = false;
guiMenu.SetActive(false);
}
Error:
NullReferenceException: Object reference not set to an instance of an object MouseLook.Update () (at Assets/Standard Assets/Character Controllers/Sources/Scripts/MouseLook.cs:44)
It seems that the code you've given here is in an Update. So the guiMenu object is being found and stored every frame.
What you want to do is cache the object in the Awake or Start function, and the rest of the code will work just fine. Also note that caching is always good practice.
//This is the Awake () function, part of the Monobehaviour class
//You can put this in Start () also
UnityEngine.GameObject guiMenu;
void Awake () {
guiMenu = GameObject.FindWithTag ("Canvas");
}
// Same as your code
void Update () {
if ((Input.GetKey ("p")) && (stoppedMovement == true)) {
stoppedMovement = false;
walkScript.enabled = true;
guiMenu.SetActive(true);
} else if ((Input.GetKey ("p")) && (stoppedMovement == false)) {
stoppedMovement = true;
walkScript.enabled = false;
guiMenu.SetActive(false);
}
}