Trying to make a button hover when cursor is over it - c#

Image of Unity screen and inspector
So I am trying to make a button larger upon a mouse hover. I wrote the code similar to what I found in a YouTube tutorial but it is not working. I believe I have the button setup correctly in the inspector but it is not working when I hover over the button.
public class Hover : MonoBehaviour
{
public void PointerEnter()
{
transform.localScale = new Vector2(1.5f, 1.5f);
}
public void PointerExit()
{
transform.localScale = new Vector2(1f, 1f);
}
}

Try to change the methods name to "OnPointerEnter"/"OnPointerExit". Otherwise it could be that the Image would not scale up with the size of object.
Therefore get the image reference and scale it directly:
private Image playButton;
public void Start()
{
image = GetComponent<Image>();
}
public void PointerEnter()
{
image.transform.localScale = new Vector2(1.5f, 1.5f);
}
public void PointerExit()
{
image.transform.localScale = new Vector2(1f, 1f);
}

I would implement IPointerEnterHandle / IPointerExitHandler like e.g.
public class Hover : MonoBehaviour, IPointerEnterHandle, IPointerExitHandler
{
public void OnPointerEnter(EventSystems.PointerEventData eventData);
{
transform.localScale = new Vector2(1.5f, 1.5f);
}
public void OnPointerExit(EventSystems.PointerEventData eventData);
{
transform.localScale = new Vector2(1f, 1f);
}
}
and don't use the EventTrigger at all.
Alternatively you could also directly inherit and overwrite e.g.
public class HoverButton : Button
{
public override void OnPointerEnter(PointerEventData eventData)
{
base.OnPointerEnter(eventData);
transform.localScale = new Vector2(1.5f, 1.5f);
}
public override void OnPointerExit(PointerEventData eventData)
{
base.OnPointerExit(eventData);
transform.localScale = new Vector2(1f, 1f);
}
}
Note though: Since the Button has a special Inspector you will not be able to expose any fields to the Inspector unless you implement your own custom editor inheriting from ButtonEditor.

Related

Trying to get text to follow the object calling it

I've attached my code, tried a few different things here and there but to no avail. If someone can help out and explain why your code works that would be amazing, thank you.
I have NPCTextPerson as a component and this is the script, it shows above the object but if they move it will not update the text location.
I am looking to update the script to display the text as is, but to update and follow the object until the text disappears.
This is the "NPCTextPerson" component script attached to the game object.
public class NPCTextPerson : Collidable
{
public string message;
public float cooldown = 4.0f;
private float lastShout;
protected override void Start()
{
base.Start();
lastShout = -cooldown;
}
protected override void OnCollide(Collider2D coll)
{
if (Time.time - lastShout > cooldown)
{
lastShout = Time.time;
GameManager.instance.ShowText(message, 25, Color.white, transform.position + new Vector3(0,0.16f,0), Vector3.zero, cooldown);
}
}
}
Here is the "Game Manager" script handling the floating text module
public class GameManager : MonoBehaviour
{
public static GameManager instance;
private void Awake()
{
if(GameManager.instance != null)
{
Destroy(gameObject);
Destroy(player.gameObject);
Destroy(floatingTextManager.gameObject);
Destroy(hud);
Destroy(menu);
return;
}
//PlayerPrefs.DeleteAll();
instance = this;
SceneManager.sceneLoaded += LoadState;
SceneManager.sceneLoaded += OnSceneLoaded;
}
// Resoures for the game
public List<Sprite> playerSprites;
public List<Sprite> weaponSprite;
public List<int> weaponPrices;
public List<int> xpTable;
// References
public Player player;
public Weapon weapon;
public FloatingTextManager floatingTextManager;
public RectTransform hitpointBar;
public Animator deathMenuAnim;
public GameObject hud;
public GameObject menu;
// Logic
public int pesos;
public int experience;
// Floating Text
public void ShowText(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
{
floatingTextManager.Show(msg, fontSize, color, position, motion, duration);
}
This is the "Floating Text" script handling all the show/update/get
public class FloatingTextManager : MonoBehaviour
{
public GameObject textContainer;
public GameObject textPrefab;
private List<FloatingText> floatingTexts = new List<FloatingText>();
private void Update()
{
foreach (FloatingText txt in floatingTexts)
txt.UpdateFloatingText();
}
public void Show(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
{
FloatingText floatingText = GetFloatingText();
floatingText.txt.text = msg;
floatingText.txt.fontSize = fontSize;
floatingText.txt.color = color;
floatingText.go.transform.position = Camera.main.WorldToScreenPoint(position); // Transer world space to screen space so we can use it in the UI
floatingText.motion = motion;
floatingText.duration = duration;
floatingText.Show();
}
private FloatingText GetFloatingText()
{
FloatingText txt = floatingTexts.Find(t => !t.active);
if(txt == null)
{
txt = new FloatingText();
txt.go = Instantiate(textPrefab);
txt.go.transform.SetParent(textContainer.transform);
txt.txt = txt.go.GetComponent<Text>();
floatingTexts.Add(txt);
}
return txt;
}
}

Proper way to "spawn" game objects. (I want to spawn projectiles)

Hey all I made the following class to act as "bullets" in my game and I don't know how to construct these bullet objects with the params that I want (determined at runtime) and spawn them in the game.
My first attempt looked like this:
if (canShoot())
{
shotCoolDown = FRAMES_BETWEEN_SHOTS;
Bullet bullet = new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL).setDirectionOffset(internalRecoil.getRecoil());
}
but i get the following warnign from the unity editor:
You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all
What is the proper way to spawn these bullets and to set the fields as I want them?
For more info here is the bullet class
public class Bullet : MonoBehaviour
{
private Rigidbody rigidbody;
private float wobble;
private float loft;
private float initialVel;
private Vector2 initialDirectionOffset;
private bool wobbleDirection = false;
private void Awake()
{
this.rigidbody = this.GetComponent<Rigidbody>();
}
private void Start()
{
transform.Rotate(initialDirectionOffset);
rigidbody.AddForce(initialVel*transform.forward);
rigidbody.AddForce(loft*transform.up);
}
private void FixedUpdate()
{
if (wobbleDirection)
{
rigidbody.AddForce(transform.right * wobble);
wobbleDirection = false;
}
else
{
rigidbody.AddForce(-transform.right * wobble);
wobbleDirection = true;
}
}
public Bullet setWobble(float wobble)
{
this.wobble = wobble;
return this;
}
public Bullet setLoft(float loft)
{
this.loft = loft;
return this;
}
public Bullet setInitialVel(float initialVel)
{
this.initialVel = initialVel;
return this;
}
public Bullet setDirectionOffset(Vector2 offset)
{
this.initialDirectionOffset = offset;
return this;
}
}
For more info here is the full "gun" class that spawns the bullets.
public class Gun : MonoBehaviour
{
private int FRAMES_BETWEEN_SHOTS = 10;
private int shotCoolDown = 0;
private const float LOFT = 100F;
private const float WOBBLE = 100F;
private const float INITIAL_VEL = 100F;
private Vector3 directionOffset;
private Recoil internalRecoil;
private void Awake()
{
internalRecoil = this.GetComponent<Recoil>();
if (internalRecoil == null)
{
throw new Exception("Could not find recoil component");
}
}
private void FixedUpdate()
{
if (shotCoolDown > 0)
{
shotCoolDown--;
}
}
private bool canShoot()
{
return shotCoolDown == 0;
}
public void performShoot()
{
if (canShoot())
{
//need to have a recoil component that reacts to bullet fire. then adjusts back to 0,0,0
shotCoolDown = FRAMES_BETWEEN_SHOTS;
Bullet bullet = new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL).setDirectionOffset(internalRecoil.getRecoil());
}
}
}
My second attempt looks like:
GameObject.Instantiate(new Bullet().setLoft(LOFT).setWobble(WOBBLE).setInitialVel(INITIAL_VEL)
.setDirectionOffset(internalRecoil.getRecoil()));
is this the right way to do it???
As 3Dave mentioned, the best way to do this would be to instantiate a prefab. Assuming you will be dealing with multiple projectiles, I like to separate this into a utility function for instantiating prefabs at a given position.
public static class UnityUtil {
public static GameObject instantiatePrefab(
Object prefab,
Vector3 position,
Transform? parent = null
){
// Create an instance of the prefab
GameObject instance = Object.Instantiate(prefab, position, Quaternion.identity) as GameObject;
// Set the parent
if(parent != null){
instance.transform.parent = parent;
}
return instance;
}
}
Then you could have code like
Transform projectileHolder;
GameObject myBulletPrefab;
Vector3 bulletPosition;
...setup variables...
var BulletGameObj = UnityUtil.instantiatePrefab(myBulletPrefab, bulletPosition, projectileHolder);
Bullet bullet = BulletGameObj.GetComponent<Bullet>();
I keep some other functions in my util for dealing with generic gameobject cases, you can see my full UnityUtil class here

Unity: 'Jostick.inputVector' is inaccessible due to its protection level

I am a beginner using C# and trying to create a touch controller, but when it compiles it gives following error:
Jostick.inputVector is inaccessible due to its protection level.
Following is the script:
using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;
public class CalleAll : MonoBehaviour
{
public FixedJoystick MoveJoystick;
public FixedTouchField TouchField;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
var fps = GetComponent<RigidbodyFirstPersonController>();
fps.RunAxis = MoveJoystick.inputVector;
fps.mouseLook.LookAxis=TouchField.TouchDist;
}
}
And this is the script file.
using UnityEngine;
using UnityEngine.EventSystems;
public class FixedJoystick : Joystick
{
public Vector2 joystickPosition = Vector2.zero;
private Camera cam = new Camera();
void Start()
{
joystickPosition = RectTransformUtility.WorldToScreenPoint(cam, background.position);
}
public override void OnDrag(PointerEventData eventData)
{
Vector2 direction = eventData.position - joystickPosition;
///here it is
inputVector = (direction.magnitude > background.sizeDelta.x / 2f) ? direction.normalized : direction / (background.sizeDelta.x / 2f);
ClampJoystick();
handle.anchoredPosition = (inputVector * background.sizeDelta.x / 2f) * handleLimit;
}
public override void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public override void OnPointerUp(PointerEventData eventData)
{
inputVector = Vector2.zero;
handle.anchoredPosition = Vector2.zero;
}
}
The error is because the class Joystick has a protected member already named inputVector - you cannot use it from within types other than its subclasses (which is why FixedJoystick can use it, but not CalleAll, as CalleAll does not derive from Joystick).
You can make the data available to consumers by creating a readonly property that exposes the data:
class FixedJoystick : Joystick
{
public Vector2 InputVector
{
get { return this.inputVector; }
}
}
class CalleAll : MonoBehaviour
{
void Update()
{
var fps = GetComponent<RigidbodyFirstPersonController>();
fps.RunAxis = this.MoveJoystick.InputVector;
}
}

Update Camera Position Using Right Arrow Key

Hello in my below code i am updating my camera position using UI Buttons which is working fine what i want is to do this same process but by pressing right arrow key like if i press right arrow key camera will change its position to point A then stops there and when again i press the same arrow key the camera will change its position to point B and as in the code i have a different function to be called on different ui button so on thanks here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class cam : MonoBehaviour
{
[Header("Locations where camera will update its position step by step")]
public Transform handleview;
public Transform needle1view;
public Transform wallview;
public Transform handletwoview;
public Transform needle2view;
public Transform switchview;
public Transform lastswitchview;
public GameObject Animatebtn;
Animator animatebtnanim;
[Header("UI Buttons")]
public GameObject inspectionbtn;
public GameObject animatebtn;
public GameObject step2btn;
public GameObject step3btn;
public GameObject step4btn;
public GameObject step5btn;
public GameObject step6btn;
public GameObject step7btn;
[Header("Inspection Views")]
public Transform startview;
public Transform handle1view;
public Transform motorview;
public Transform handle2view;
[Header("Move Boolean")]
public bool move = false;
[Header("Speed At Which Cam Moves")]
public float speed;
[Header("Current View/position Of Camera")]
Transform currentVIEW;
[Header("Current Angel Of Camera")]
Vector3 currentangel;
[Header("FieldofView of Camera ")]
public float camFieldOFview = 24f;
public int track = 0;
// Use this for initialization
void Start()
{
Camera.main.fieldOfView = camFieldOFview;
animatebtnanim = Animatebtn.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (move)
{
//float step = speed * Time.deltaTime;
//transform.position = Vector3.MoveTowards(transform.position, currentVIEW.position, step);
transform.position = Vector3.Lerp(transform.position, currentVIEW.position, Time.deltaTime * speed);
currentangel = new Vector3(Mathf.LerpAngle(transform.rotation.eulerAngles.x, currentVIEW.transform.rotation.eulerAngles.x, Time.deltaTime * speed),
Mathf.LerpAngle(transform.rotation.eulerAngles.y, currentVIEW.transform.rotation.eulerAngles.y, Time.deltaTime * speed),
Mathf.LerpAngle(transform.rotation.eulerAngles.z, currentVIEW.transform.rotation.eulerAngles.z, Time.deltaTime * speed));
transform.eulerAngles = currentangel;
}
//if (Input.GetKey(KeyCode.RightArrow))
//{
// if (track == 7)
// track = 1;
// if (track == 1)
// {
// moveTOstartVIEW();
// move = true;
// }
// else if (track == 2)
// {
// moveTOhandleONEview();
// move = true;
// }
// track += 1;
//}
}
// this function will lerp camera to startview location
public void moveTOstartVIEW()
{
currentVIEW = startview;
move = true;
}
public void moveTOhandleONEview()
{
currentVIEW = handle1view;
move = true;
animatebtnanim.SetBool("start", true);
animatebtnanim.SetBool("move", false);
}
public void moveTOmotorview()
{
currentVIEW = motorview;
move = true;
}
public void moveTOhandleTWOview()
{
currentVIEW = handle2view;
move = true;
}
public void Handleview()
{
currentVIEW = handleview;
inspectionbtn.SetActive(false);
animatebtn.SetActive(false);
move = true;
}
public void Needleoneview()
{
currentVIEW = needle1view;
step2btn.SetActive(false);
move = true;
}
public void Wallview()
{
currentVIEW = wallview;
move = true;
step3btn.SetActive(false);
}
public void Handletwoview()
{
currentVIEW = handletwoview;
move = true;
step4btn.SetActive(false);
}
public void Needletwoview()
{
currentVIEW = needle2view;
move = true;
step5btn.SetActive(false);
}
public void Switchview()
{
currentVIEW = switchview;
move = true;
step6btn.SetActive(false);
}
public void lastSwitchview()
{
currentVIEW = lastswitchview;
move = true;
step7btn.SetActive(false);
}
}
As I understood you have a usual UI.Button component and now want to do the same thing on a certain keyboard key as this button would do in onClick.
Solution 1: Extending the Button
I would simply invoke the Button's onClick event after getting a certain KeyCode by putting the following component right next to the Button component on your button objects (not on the camera)
using UnityEngine;
// make sure you are not accidentely using
// UnityEngine.Experimental.UIElements.Button
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class KeyboardButton : MonoBehaviour
{
// Which key should this Button react to?
// Select this in the inspector for each Button
public KeyCode ReactToKey;
private Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
// Wait for the defined key
private void Update()
{
// If key not pressed do nothing
if (!Input.GetKeyDown(ReactToKey)) return;
// This simply tells the button to execute it's onClick event
// So it does exactly the same as if you would have clicked it in the UI
_button.onClick.Invoke();
}
}
Solution 2: Replacing the Button
Alternatively if you do not want to use a Button anymore at all you can add your own UnityEvent e.g. OnPress to the above script instead
using UnityEngine;
using UnityEngine.Events;
public class KeyboardButton : MonoBehaviour
{
// Which key should this Button react to?
// Select this in the inspector for each Button
public KeyCode ReactToKey;
// reference the target methods here just as
// you would do with the Button's onClick
public UnityEvent OnPress;
// Wait for the defined key
private void Update()
{
// If key not pressed do nothing
if (!Input.GetKeyDown(ReactToKey)) return;
OnPress.Invoke();
}
}

Entity Component System c#

I'm currently creating a 2D game engine in C#. At the moment, I'm implementing an entity component system.
My structure is as follows:
Entity Class: Contains a list of IGameComponent's, you can add, remove and delete any component by class type. (ie; entity.RemoveComponent(typeof(Transform));. It also contains a parent Entity, and a list child entities.
IGameComponent Interface: For now, is just an empty interface. (Note that: Components only contain data, and not functionality)
Entity Pool: Contains a list of all the active objects in the game, it's also used to create and destroy entities.
Everything so far is great.
However, I'm faced with a problem. Since components only contain data I need a way to initialize, update and render the components and I'd rather not just add a bunch of virtual methods to a GameComponent class, however I don't know of any other way to resolve it.
What are my options?
EDIT:
I've seen that Unity uses methods like 'SendMessage' which I can only assume uses reflection to call methods. Should I implement something similar?
I don't know if you still need it, but I have made something similar a few years ago and it might help you. It's written in C# built on top of MonoGame/XNA
You GameObject class can look like this
public class GameObject
{
List<GameObjectComponent> _goComponent = new List<GameObjectComponent();
public T GetComponent<T>() where T : GameObjectComponent
{
foreach (GameObjectComponent goc in _goComponent)
if (goc.GetType().Equals(typeof(T)))
return (T)goc;
return null;
}
public void AddComponent(GameObjectComponent gameObjectComponent)
{
_goComponent.Add(gameObjectComponent);
gameObjectComponent.gameObject = this;
gameObjectComponent.Init();
}
public virtual void Update(GameTime gameTime)
{
foreach (GameObjectComponent _goc in _goComponent)
_goc.Update(gameTime);
}
public static void Instantiate(GameObject gameObject)
{
Scene._AddedGO.Add(gameObject);
}
public static void Destroy(GameObject gameObject)
{
Scene._RemoveGO.Add(gameObject);
}
}
GameObjectComponent is similar to MonoBehaivior from Unity3D
public class GameObjectComponent
{
public GameObject gameObject;
public GameObjectComponent()
{
}
public virtual void Init()
{
}
public virtual void Update(GameTime gameTime)
{
}
}
and then you Inherit other classes like so:
public class Sprite : GameObjectComponent
{
public Texture2D texture;
public Vector2 origin = Vector2.Zero;
public Rectangle rect;
public Rectangle sourceRect;
public Color color = Color.White;
public float rotation = 0f;
private float layerDepth = 0f;
public int scale = 1;
public Sprite()
{
}
public void Load(string path)
{
texture = Setup.ContentDevice.Load<Texture2D>(path);
}
}
now you can finally create you Player GameObject
class Player : GameObjectComponent
{
float speed = 150f;
KeyboardState keyState;
float pos_X;
float pos_Y;
int rect_X;
int rect_Y;
public Player(float x, float y, int rx, int ry)
{
pos_X = x;
pos_Y = y;
rect_X = rx;
rect_Y = ry;
}
public override void Init()
{
Sprite sprite = new Sprite();
gameObject.AddComponent(sprite);
gameObject.GetComponent<Sprite>().Load("Sprites/MainGuySpriteSheet_0");
gameObject.GetComponent<Sprite>().scale = 1;
gameObject.GetComponent<Sprite>().rect = new Rectangle(46, 0, 32, 36);
Transform transform = new Transform();
gameObject.AddComponent(transform);
// gameObject.GetComponent<Transform>().position = new Vector2(Screen.width / 2 - gameObject.GetComponent<Sprite>().rect.Width, Screen.height / 2 - gameObject.GetComponent<Sprite>().rect.Height);
gameObject.GetComponent<Transform>().position = new Vector2(pos_X, pos_Y - 32 * (gameObject.GetComponent<Sprite>().scale - 1));
RectCollider collider = new RectCollider();
gameObject.AddComponent(collider);
gameObject.GetComponent<RectCollider>().Set(gameObject.GetComponent<Sprite>(), gameObject.GetComponent<Transform>());
SpriteRenderer render = new SpriteRenderer();
gameObject.AddComponent(render);
gameObject.GetComponent<SpriteRenderer>().layer = 1;
gameObject.GetComponent<SpriteRenderer>().Set(gameObject.GetComponent<Sprite>());
}
public override void Update(GameTime gameTime)
{
//movex = transform.position.X -= 25 * gameTime.DeltaTime();
if (Keyboard.GetState().IsKeyDown(Keys.Left))
gameObject.GetComponent<Transform>().Move(-speed * gameTime.DeltaTime(), 0);
else if (Keyboard.GetState().IsKeyDown(Keys.Right))
gameObject.GetComponent<Transform>().Move(speed * gameTime.DeltaTime(), 0);
else if (Keyboard.GetState().IsKeyDown(Keys.Down))
gameObject.GetComponent<Transform>().Move(0, speed * gameTime.DeltaTime());
else if (Keyboard.GetState().IsKeyDown(Keys.Up))
gameObject.GetComponent<Transform>().Move(0, -speed * gameTime.DeltaTime());
if (Keyboard.GetState().IsKeyDown(Keys.Space) && !keyState.IsKeyDown(Keys.Space))
{
GameObject tomato = new GameObject();
tomato.AddComponent(new Tomato());
tomato.GetComponent<Transform>().position = gameObject.GetComponent<Transform>().position;
GameObject.Instantiate(tomato);
}
if (Keyboard.GetState().IsKeyDown(Keys.Q) && !keyState.IsKeyDown(Keys.Q))
{
SceneManager.LoadScene(new AnotherOne());
}
keyState = Keyboard.GetState();
gameObject.GetComponent<Transform>().position.Y = MathHelper.Clamp(gameObject.GetComponent<Transform>().position.Y, 0, Screen.bounds.Height - gameObject.GetComponent<Sprite>().rect.Height * gameObject.GetComponent<Sprite>().scale);
gameObject.GetComponent<Transform>().position.X = MathHelper.Clamp(gameObject.GetComponent<Transform>().position.X, 0, Screen.bounds.Width - gameObject.GetComponent<Sprite>().rect.Width * gameObject.GetComponent<Sprite>().scale);
}
}
I hope it's not too confusing and helps you a little bit.
To make it clearer I leave a link to the git here: https://github.com/Memorix101/MonoGame_ComponentSystem
Cheers, Memorix101 :)

Categories

Resources