Good Day all, I am trying to make a simple 2D game and here is how it works. Assume there is a sprite "tent", and whenever i clicked the tent, the console will print out a message. Sounds straightforward is it? However I'm like stuck in the middle of it and I know I am gonna facepalmed myself so hard after this. What I did in my script is:
public abstract class Player : MonoBehaviour {
protected string _name;
// Use this for initialization
public Player(string name)
{
_name = name;
}
public string Name
{
get { return _name; }
set { _name = value; }
}
void Start () {
}
// Update is called once per frame
void Update () {
}}
Next I have a child class called Civilian
public class Civilian : Player {
// Use this for initialization
public Civilian(string name):base(name)
{
}
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Then in my script "Tentclicked", i want to called the function of sleep when the sprite is clicked.
public class tentclicked : MonoBehaviour {
void OnMouseDown()
{
// c.Sleep();
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
And you are wondering what is c and what it is point to? I instantiated a new class in another script called testing1.
public class testing1 : MonoBehaviour
{
public Text p1name;
public void Awake()
{
//p1name.text = "Hello";
//Civilian C = Scriptss.AddComponent<Civilian>();
//GameObject theCivilian = GameObject.Find("Scriptss");
// Civilian c = theCivilian.GetComponent<Civilian>();
//c.Name = Testingsavename.playernames.username;
//c.Name = "Hello";
}
// Use this for initialization
void Start()
{
if (Choosechar.choice.choicecount == 1)
{
Civilian c = new Civilian(Testingsavename.playernames.username);
p1name = GetComponent<Text>();
p1name.text = c.Name;
}
I have already add a circle collider to my sprite. The error is that in tentclicked, c does not exist in context. So i suspect it may be that unity does not know what c is. I am thinking of making civilian class a static one, and just called Civilian.civilian.Sleep() in tentclicked script....
"c" does not exist in this context because your tentclicked class has no reference to it. Find "c" with GameObject.Find(string name) and assign the gameobject value to a variable in tentclicked
You could raycast from the current mouse position towards the object (just make sure that the object has a collider.
void OnMouseDown()
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if ( Physics.Raycast (ray,out hit,100.0f))
{
Civilian c = hit.collider.gameObject.GetComponent<Civilian>();
c.Sleep();
}
}
Related
I've trying to make an adventure game which saves different bools in order to get to the next scene. The problem is that one bool is in another scene with makes it null. Is there any advice?
public class Farmer : MonoBehaviour
{
public bool NextLevel = false;
public Cow1 cow1;
public Cow2 cow2;
public Cow3 cow3;
public Dialogue dialogue;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (GetComponent<Cow1>().getIsDisplayed() && GetComponent<Cow2>().getIsDisplayed() && GetComponent<Cow3>().getIsDisplayed())
{
NextLevel = true;
}
if (NextLevel == true)
{
FindObjectOfType<DialogueManager>().startDialogue(dialogue);
}
}
}
Yes, there is quite an easy way to do this, simply give a game object the DontDestroyOnLoad property
{
public bool NextLevel = false;
public Cow1 cow1;
public Cow2 cow2;
public Cow3 cow3;
public Dialogue dialogue;
// Start is called before the first frame update
void Start()
{
DontDestroyOnLoad(this.gameObject);
}
// Update is called once per frame
void Update()
{
if (GetComponent<Cow1>().getIsDisplayed() && GetComponent<Cow2>().getIsDisplayed() && GetComponent<Cow3>().getIsDisplayed())
{
NextLevel = true;
}
if (NextLevel == true)
{
FindObjectOfType<DialogueManager>().startDialogue(dialogue);
}
}
}
This will make your game object persistent through scene changes
You can make use of multi-scene editing so you have some values and variables carry on between your scenes. You can learn more about this here.
Now I am doing a project for my final term in university and my area changed the scene by gazing(google VR SDK).
At first, I just put a code to change the scene. It worked. But I want some enhance, so I used gaze timer which I watched at youtube (link: https://www.youtube.com/watch?v=bmMaVTV8UqY)
Now, the gaze Timer animation is working but the SceneSwitcher function in NexScene1 code isn't working.
I've done 'build' after adding the new scene that I add gaze timer function.
Also, I used tagged which shown in the youtube.
That's all I did.
public class VRGaze : MonoBehaviour {
public Image imgGaze;
public float totalTime = 2;
bool gvrStatus;
float gvrTimer;
public int distanceOfRay = 10;
private RaycastHit _hit;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (gvrStatus)
{
gvrTimer += Time.deltaTime;
imgGaze.fillAmount = gvrTimer / totalTime;
}
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.5f));
if(Physics.Raycast(ray, out _hit, distanceOfRay))
{
if(imgGaze.fillAmount == 1 && _hit.transform.CompareTag("NexScene1"))
{
_hit.transform.gameObject.GetComponent<NexScene1>().SceneSwitcher();
}
}
}
public void GVROn() {
gvrStatus = true;
}
public void GVROff() {
gvrStatus = false;
gvrTimer = 0;
imgGaze.fillAmount = 0;
}
}
public class NexScene1 : MonoBehaviour {
public UnityEngine.UI.Scrollbar obj_scroll_;
public GameObject player;
public void PointEnter()
{
StartCoroutine(TimeToAction());
}
public void PointExit()
{
StopAllCoroutines();
}
public void SceneSwitcher()
{
SceneManager.LoadScene("Page2");
}
void Start () {
}
// Update is called once per frame
void Update () {
}
}
Not an actual error but just the SwitchScene function is not called at VRGaze
Not an error but the console says:
It is recommended to use GvrPointerPhysicsRaycaster or
GvrPointerGrahpicRaycaster with GvrPointerInputModule.
I tried both setting enabled to true and SetActive(true) to diplay a Gameover Image. However, none of them works. I have a public Image gameOverImage declared and set the gameOverImage.enabled in the Start() to false.
private void Start()
{
gameOverImage.enabled = false;
}
Then in one of my function, I put:
public void killAt(Vector2 loc)
{
foreach (GameObject obj in setup.GetActive())
{
if (obj.GetComponent<PieceInfo>().GetLocation() == loc)
{
if (obj.GetComponent<PieceInfo>().GetPieceType() == 'G')
{
gameOver = true;
gameOverImage.enabled = true;
Debug.Log("?????");
}
setup.deactivate(obj);
break;
}
}
}
The console does have ????? logged but no gameOverImage displayed in the game view. The game is over because I couldn't click my game any more. Any ideas? I also tried UI text. It doesn't work as well.
In Unity in order to activate an object you need to have it in the scene. If the GameObject does not exist in the scene, or in your case the UI Element that contains the Image, is not in your scene SetActive(true) or Enabled = true will not have any effect. You will need to instantiate the object. To make it exist in your world.
Prefabs, are useful to store a common configuration that can be used multiple times in your game but they do not exist in the scene, that is why you have to instantiate them.
For your GameOver Image you have a few options the simplest is this:
using UnityEngine;
using UnityEngine.UI;
public class EnableUI : MonoBehaviour {
public Image GameOverImage;
// Use this for initialization
void Start () {
GameOverImage.gameObject.SetActive(false);
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.Space))
{
GameOverImage.gameObject.SetActive(true);
}
}
}
If you want to instantiate it:
using UnityEngine;
public class EnableUI : MonoBehaviour {
// This is a prefab that is canvas with your game over image nested as a child image UI under it
public GameObject GameOverObject;
// Use this for initialization
void Start () { }
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(GameOverObject);
}
}
}
I am working on 2D game.
When player collides with BOMBPrefab lose 1 heart (initial 3 heart), if collides 3 times = GameOver.
Thats is the code (works fine for BombPrefab):
using UnityEngine;
using System.Collections;
public class Heart : MonoBehaviour {
public Texture2D[] initialHeart;
private int heart;
private int many;
// Use this for initialization
void Start () {
GetComponent<GUITexture>().texture = initialHeart[0];
heart = initialHeart.Length;
}
// Update is called once per frame
void Update () {}
public bool TakeHeart()
{
if (heart < 0) {
return false;
}
if (many < (heart - 1)) {
many += 1;
GetComponent<GUITexture> ().texture = initialHeart [many];
return true;
} else {
return false;
}
}
}
I have a second HeartPrefab, I want to check when player collides... IF I have 3 hearts do nothing, IF have 1 or 2 hearts ADD extra heart.
BombPrefab Scrip:
using UnityEngine;
using System.Collections;
public class Bomb : MonoBehaviour
{
public AudioClip clipBomba;
private Heart heart;
private Gerenciador gerenciador;
void Awake ()
{
}
// Use this for initialization
void Start ()
{
gerenciador = FindObjectOfType (typeof(Gerenciador)) as Gerenciador;
}
// Update is called once per frame
void Update ()
{
}
void OnCollisionEnter2D (Collision2D colisor)
{
if (colisor.gameObject.tag == "floor") {
Destroy (gameObject, 2f);
} else {
if (colisor.gameObject.tag == "Bee") {
Som();
heart= GameObject.FindGameObjectWithTag ("Heart").GetComponent<Vidas> () as Vidas;
if (heart.TakeHeart ()) {
Destroy (gameObject);
} else {
gerenciador.GameOver ("GameOver");
}
}
}
}
void Som()
{
GetComponent<AudioSource> ().clip = clipBomb;
AudioSource.PlayClipAtPoint (clipBomb, transform.position);
}
}
First of all try not use GetComponent<>() in update and functions that are run often. It is better to cache components in Start() method. Using FindGameObjectWith...() is also not very efficient.
I would make it differently, each heart as a separate UI element (Toggle), with two states active and inactive. Then your player should have a list of those hearts and methods that allow to take damage and gain life.
int currentHeartsCount = 3;
int maxHeartsCount = 3;
List<Heart> hearts = new List<Heart>();
public void TakeDamage(int damage) {
ChangeHearts(-damage);
}
public void GainLife(int life) {
ChangeHearts(life);
}
private void ChangeHearts(int amount) {
currentHeartsCount += amount;
if(currentHeartsCount> maxHeartsCount)
currentHeartsCount = maxHeartsCount;
if(currentHeartsCount<=0) {
// call player dead code
}
int i = 1;
foreach(Heart heart in hearts) {
heart.SetHeartActive(i<=currentHeartsCount);
i++;
}
}
This is a simplified solution to give you an idea. It is more robust than yours because you can easily change start heart count, and make things like heart "overcharge". Just add base hearts, set max to desired value, and now you can create some special power ups which increase hearts over the initial limit.
i want to swap the gems with the gemcomponent only,that is invisible i tried the snippet blow ,but i'am getting nullexception error as:
NullReferenceException: Object reference not set to an instance of an object
board.SwapGem () (at Assets/Resources/Scripts/board.cs:81)
Gem.OnMouseDown () (at Assets/Resources/Scripts/Gem.cs:59)
UnityEngine.SendMouseEvents:DoSendMouseEvents(Int32, Int32)
what am i doing wrong ??
board.cs
public List<Gem> gems = new List<Gem>();
public Gem LastGem;
public Vector3 gem1start,gem2start,gem1end,gem2end;
public Gem gem1,gem2; // gem to change i
public Gem gemComponent;
// Use this for initialization
void Start () {
gem1start=gem1.transform.position;
gem1end = gemComponent.transform.position;
}
// Update is called once per frame
void Update () {
}
}
public void SwapGem()
{
gem2start = gem1start;
gem2end = gem1end;
gem1.transform.position = gem2start;
gemComponent.transform.position = gem2end;
}
gem.cs
public void OnMouseDown()
{
if (!GameObject.Find("board").GetComponent<board>().isSwapping)
{
ToggleSelector ();
GameObject.Find ("board").GetComponent<board> ().SwapGem ();
}
}