How can i add a button box to scene view ? (Not ui) - c#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class Menu : MonoBehaviour {
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown("m"))
Debug.Log("menu");
}
}
First the Update function is not calling in scene view.
And second how can i add in the Start or in other event a box menu like ? For example:
GUILayout.Window(0, new Rect(10, 10, 100, 100), (id)=> {
GUILayout.Button("A Button");
},

Solution:
using UnityEditor;
using UnityEngine;
public class SceneGUI : EditorWindow
{
[MenuItem("Window/Scene GUI/Enable")]
public static void Enable()
{
SceneView.onSceneGUIDelegate += OnScene;
Debug.Log("Scene GUI : Enabled");
}
[MenuItem("Window/Scene GUI/Disable")]
public static void Disable()
{
SceneView.onSceneGUIDelegate -= OnScene;
Debug.Log("Scene GUI : Disabled");
}
private static void OnScene(SceneView sceneview)
{
Handles.BeginGUI();
if (GUILayout.Button("Destroy Objects", GUILayout.Width(100), GUILayout.Height(100)))
{
}
Handles.EndGUI();
}
}

Related

I tried scriptable object as an input reader from input actions script but it won't work for some reason

i'm trying to invoke input events from a scriptable object as a channel or a layer between the input action script and the player like what unity does in its open project "chop chop" but it is not working at all with no errors or warnings . i don't know why ? can u help me please ? (using the new input system) this is the code for the channel :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.InputSystem;
[CreateAssetMenu(fileName ="testScriptableObject", menuName ="game/test SO")]
public class InputSOChannel : ScriptableObject
{
public event Action playerFire;
private TestControls testControl;
private void OnEnable() {
testControl = new TestControls();
testControl.test.fire.started += onfire;
}
private void onfire(InputAction.CallbackContext context)
{
playerFire?.Invoke();
Debug.Log("the event invoked!");
}
private void OnDisable() {
testControl.test.fire.started -= onfire;
}
}
and this for the player or input receiver :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectController : MonoBehaviour
{
[SerializeField] InputSOChannel inputSOChannel;
private void OnEnable() {
inputSOChannel.playerFire += isfiring;
}
private void OnDisable() {
inputSOChannel.playerFire -= isfiring;
}
private void isfiring()
{
Debug.Log("the event fired from the lowend!");
}
}
i really appreciate any help . thank you!
i just forgot to enable the input action script , beginner's mistake

Change function within unity inspector

I have a gameObject that needs to call lots of other functions. I was hoping to do something like this
Where I can select the gameobject and script for it to run. I can't figure out how to do this.
I'm calling a function on button click for a gui.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class AvatarSystem : MonoBehaviour
{
public Button general;
public Button face;
public Button hair;
public Button eyebrows;
public Button clothing;
// Start is called before the first frame update
void Start()
{
var root = GetComponent<UIDocument>().rootVisualElement;
general = root.Q<Button>("general");
face = root.Q<Button>("face");
hair = root.Q<Button>("hair");
eyebrows = root.Q<Button>("eyebrows");
clothing = root.Q<Button>("clothing");
general.clicked += generalClicked;
face.clicked += faceClicked;
hair.clicked += hairClicked;
eyebrows.clicked += eyebrowsClicked;
clothing.clicked += clothingClicked;
}
void generalClicked()
{
}
void faceClicked()
{
}
void hairClicked()
{
}
void eyebrowsClicked()
{
}
void clothingClicked()
{
}
}
The 5 bottom functions should do something like the top image. Thanks
You can this script which creates buttons in the inspector.
This should be outside of your AvatarSystem class.
using Unity.Editor;
[CustomEditor(typeof(AvatarSystem))]
public class AvatarSystemGUI : Editor
{
public override void OnInspectorGUI()
{
AvatarSystem t = AvatarSystem(target);
if (GUILayout.Button("Test"))
{
t.ExampleMethod();
}
}
}
Let me know of any problems! :)
You want to use a Unity Event
You can use UnityEvent<T> to pass a dynamic type in your function.
Then you can use Unity IPointerClickHandler to capture a click on the object.
You can use AddListener of UnityEvent;
you can write the code like this;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class AvatarSystem : MonoBehaviour
{
public Button general;
public Button face;
public Button hair;
public Button eyebrows;
public Button clothing;
// Start is called before the first frame update
void Start()
{
var root = GetComponent<UIDocument>().rootVisualElement;
general = root.Q<Button>("general");
face = root.Q<Button>("face");
hair = root.Q<Button>("hair");
eyebrows = root.Q<Button>("eyebrows");
clothing = root.Q<Button>("clothing");
general.onClick.AddListener(() => {
this.generalClicked();
this.faceClicked();
this.hairClicked();
this.eyebrowsClicked();
this.clothingClicked();
}) ;
}
void generalClicked()
{
}
void faceClicked()
{
}
void hairClicked()
{
}
void eyebrowsClicked()
{
}
void clothingClicked()
{
}
}

How to reset score for quizzes independently?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Resetscr : MonoBehaviour
{
public List<GameInstance> quizInstances;
// Start is called before the first frame update
void awake()
{
quizInstances[0].Score = 0;
}
// Update is called once per frame
void Update()
{
}
}
I made a quiz game and I have a score panel, score and game instance. (each test has its own score panel, score and game instance).
I need a button script that on click resets the current test and score panel that will reset the score to 0.
What should I write in my script to make this action happen (score panel and current test transport data of the score from one scene to another and I need the data to be erased just when I click that button).
Should I use a button script for each game instance or is there a way to make it universal?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
public class ScorePanel1 : MonoBehaviour
{
// better if you can already reference this via Inspector
[SerializeField] Text text;
void Awake()
{
if (!text) text = GetComponent<Text>();
// it's always save to remove listeners before adding them
// makes sure it is added only once
GameInstance1.OnScoreChanged -= OnScoreChanged;
GameInstance1.OnScoreChanged += OnScoreChanged;
// invoke once now with current value
OnScoreChanged(GameInstance1.Score);
}
private void OnDestroy()
{
GameInstance1.OnScoreChanged -= OnScoreChanged;
}
private void OnScoreChanged(int newValue)
{
text.text = "Score: " + newValue;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Score1 : MonoBehaviour
{
public Text scoreText;
public Button button;
// Use this for initialization
void Start()
{
DontDestroyOnLoad(gameObject);
if (!button) button = GetComponent<Button>();
button.onClick.AddListener(() => { GameInstance1.Score++; });
GameInstance1.OnScoreChanged -= OnScoreChanged;
GameInstance1.OnScoreChanged += OnScoreChanged;
// invoke once now with current value
Debug.LogFormat("Current Score: {0}", GameInstance1.Score);
OnScoreChanged(GameInstance1.Score);
}
private void OnDestroy()
{
GameInstance1.OnScoreChanged -= OnScoreChanged;
}
private void OnScoreChanged(int newValue)
{
scoreText.text = "Score: " + newValue;
}
// These two make not much sense .. since the value already was public
// you wouldn't need methods for this
// anyway now you could directly do it on GameInformation instead
public void AddScore(int s)
{
GameInstance1.Score += s;
}
public int GetScore()
{
return GameInstance1.Score;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public static class GameInstance1
{
// Start is called before the first frame update
private static int _score = 0;
// have an event to register listeners
public static event Action<int> OnScoreChanged;
// public property
public static int Score
{
get { return _score; }
set
{
_score = value;
// invoke an event to inform all registered listeners
OnScoreChanged?.Invoke(_score);
}
}
}
You need to provide more Details.
Look like some issues with this approach.
button.onClick.AddListener(() => { GameInstance1.Score++; });
as there is no Check whether Answer is right or wrong. It will keep adding score.
You can work around your problem by having a single Canvas for entire game and don't destroy the Canvas and gameobject keep the callback of the buttons using
DontDestroyOnLoad(gameObject);
Now you need to keep the Refrence of buttons in that script instead of all the Score1 instance, So that Each Score1 instance can add listener and remove listener when required.
Now in Start of each Score1 instance you can do subscribe to the Button Listener and remove old listeners.
private ButtoncallbackHandler buttoncallback;
void Start ()
{
buttoncallback= GameObject.FindObjectOfType<ButtoncallbackHandler >();
if(buttoncallback)
{
buttoncallback.ScoreButton.onClick.AddListener(() => AnswerValidity());
buttoncallback.ResetButton.onClick.AddListener(() => OnResetClick());
}
}
void AnswerValidity()
{
if(answerisCorrect)
{
GameInstance1.Score++;
}
else
{
///Wrong Answer Logic.
}
// Update your Text Box here
UpdateTextBox();
}
void OnResetClick()
{
// Do what you want to do in reset
UpdateTextBox();
}
Similarly Implement the ResetButton, you can do Reset Current Instacne score or all scores depends on you, Keep single textbox for entire game.

Issues with fullscreen in unity

I'm making a simple menu in Unity 2D. I created a toggle that actives the full screen option. At this point, everything is alright.
Then, I wanted to do the same, but pressing the F11 key. Here starts the problem. When I press F11, the screen becomes in fullsize, but the toggle doesn't activates and vice versa.
So, I wanted to create a C# script that checks if Screen.fullscreen is true, it activates the toggle, and if it's false, it deactivates it.
I thonk that this will solve the problem, but no. When I try to press F11 or click on the toggle, the entire window goes crazy. I don't know how to explain it, but the window will start to shake on its own.
I would appreciate if somebody helps me, thank you!
The code of the toggle is this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ToggleScreen : MonoBehaviour
{
public void togglescreen()
{
if(Screen.fullScreen == true)
{
Screen.fullScreen = false;
}
else
{
Screen.fullScreen = true;
}
}
}
The code of the F11 key is this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FullScreenMode : MonoBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.F11))
{
if (Screen.fullScreen == true)
{
Screen.fullScreen = false;
}
else
{
Screen.fullScreen = true;
}
}
}
}
And the code of the activate and deactivate is this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ChangeValue : MonoBehaviour
{
private Toggle onOffSwitch;
private void Awake()
{
onOffSwitch = GetComponent<Toggle>();
}
private void Update()
{
//onOffSwitch.isOn = Screen.fullScreen;
if(Screen.fullScreen == true)
{
onOffSwitch.isOn = true;
}
else
{
onOffSwitch.isOn = false;
}
}
}
You are repeating the fullScreen logic in the ToggleScreen script and the FullScreenMode script. I would combine these (and simplify them) into a ScreenManager class:
using UnityEngine;
public class ScreenManager : MonoBehaviour
{
Toggle onOffSwitch;
void Start()
{
// Don't forget to attach the Toggle component to this game object
onOffSwitch = GetComponent<Toggle>();
// Subscribe to onOffSwitch's onValueChanged event handler
onOffSwitch.onValueChanged.AddListener(delegate
{
// delegate method to call when onOffSwitch.onValueChanged is raised.
ToggleValueChanged(onOffSwitch);
});
}
public static void ToggleFullScreen(bool updateToggleUI)
{
var toggledValue = !Screen.fullScreen;
Screen.fullScreen = toggledValue;
onOffSwitch.isOn = updateToggleUI ? toggledValue : onOffSwitch.isOn;
}
void ToggleValueChanged(Toggle change)
{
// The toggle was already changed via the UI, don't flip it back
ToggleFullScreen(false);
}
}
Then, simply call ScreenManager.ToggleFullScreen() in the FullScreenMode script's Update() method:
using UnityEngine;
public class FullScreenMode : MonoBehaviour
{
// Don't forget to drag the ScreenManager instance to this reference in the inspector
[Serializable]
ScreenManager _screenManager;
void Update()
{
if (Input.GetKeyDown(KeyCode.F11))
{
// Change the Toggle UI since this was triggered with F11
_screenManager.ToggleFullScreen(true);
}
}
}
public class Toggler
{
bool state = false;
public void ToggleState()
{
state = !state; // This sets a Boolean value to the opposite of itself
if (state)
{
// State was just toggled on
}else{
// State was just toggled off
}
}
}

In delegate function, add the same listener event, why the same listener be called Immediately?

I'm a Chinese developers, English is not very good, please predecessors read it for editing, thanks in advance.
In Unity, i write one script to listener an Event and in delegate function, i add another script the same listener in previous Event, but why the same listener be called immediately?
The following is add another script the same listener script:
using System.Collections.Generic;
using UnityEngine;
public class SceneManager : MonoBehaviour
{
private static SceneManager m_Instance;
public static SceneManager Instance
{
get
{
if (m_Instance == null)
{
m_Instance = (SceneManager)FindObjectOfType(typeof(SceneManager));
}
if (!m_Instance)
{
Debug.LogError("SceneManager could not find himself!");
}
return m_Instance;
}
}
[HideInInspector]
public List<EventDelegate> EventDelegetDo = new List<EventDelegate>();
public void RegisterBackBtnDo()
{
EventDelegate.Add(EventDelegetDo, Do);
}
public void UnRegisterBackBtnDo()
{
EventDelegate.Remove(EventDelegetDo, Do);
}
private void Start()
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.T))
{
EventDelegate.Execute(EventDelegetDo);
}
}
private void Do()
{
Debug.Log("===============ZJDebug=============== From SceneManager");
}
}
The following is initial register listener script:
using UnityEngine;
public class TDelegate : MonoBehaviour
{
public void RegisterBackBtnDo()
{
EventDelegate.Add(SceneManager.Instance.EventDelegetDo, Do);
}
public void UnRegisterBackBtnDo()
{
EventDelegate.Remove(SceneManager.Instance.EventDelegetDo, Do);
}
private void Start()
{
RegisterBackBtnDo();
}
private void Update()
{
}
private void Do()
{
Debug.Log("===============ZJDebug=============== From TDelegate");
SceneManager.Instance.RegisterBackBtnDo();
//Invoke("WaitForTest", float.NegativeInfinity);
}
private void WaitForTest()
{
SceneManager.Instance.RegisterBackBtnDo();
}
}
I have tried multiple variations of this, if invoke float.NegativeInfinity second register it not be called Immediately, can someone tell me why? in addition to delay call There is no better way called by after? English is too bad please forgive me thanks!

Categories

Resources