I want to change the position of a instantiated game object. For that I have used a UI button when the user clicks on the button a cube will be instantiated and when user clicks on that instantiated cube and move a UI slider, the position of that cube will be changed according to the value given by the slider.
I tried this way but it doesn't work. What am I doing wrong here
using UnityEngine;
using System.Collections;
public class instantiate : MonoBehaviour
{
public GameObject cube;
public float speed = 0f;
public float pos = 0f;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 100.0f))
{
Debug.Log("Clicked");
if (hit.collider.tag == "Cube")
{
// Destroy(hit.collider.gameObject);
// Destroy(this);
speed += Input.GetAxis("Horizontal");
hit.collider.gameObject.transform.eulerAngles = new Vector3(0, 0, speed);
hit.collider.gameObject.transform.position = new Vector3(0, 0, pos);//pos
}
}
}
}
public void objinst()
{
Instantiate(cube, new Vector3(0, 0, 0), Quaternion.identity);
}
public void rotatess(float newspeed)
{
speed = newspeed;
}
public void positions(float newpos)
{
pos = newpos;
}
}
You are supposed to have a callback function that gets called when the Button is clicked and another one that gets called when the Slider value changes. I can't tell if you are doing this from the Editor but the way your functions are named, we can't tell which is one being called during Button click or Slider value change...
Put your Instantiate code in your Button callback function then put your cube moving code in the Slider value change callback function.
In your Raycast code that detects the cube click, store the Transform reference of the cube to a global Transform variable. This stored Transform is what you will use to move the cube in your Slider value change callback function.
You subscribe to Button click event with Button.onClick.AddListener(instantiateButtonCallBackFunction); then to Slider value change event with Slider.onValueChanged.AddListener(delegate { sliderCallBackFunction(cubeSlider.value); });
Here is what it should look like. Everything is done with code. Simply drag the Cube prefab, Slider and Button to the right slot and it should work. When a Button is clicked, Cube is instantiated. When the cube is clicked, you will be able to move it with the slider.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class instantiate : MonoBehaviour
{
public GameObject cubePrefab;
public Slider cubeSlider;
public Button instantiateButton;
public float speed = 0f;
public float pos = 0f;
private Transform currentObjectToDrag = null;
// Use this for initialization
void Start()
{
//Set Slider Values
cubeSlider.minValue = 0f;
cubeSlider.maxValue = 50f;
cubeSlider.value = 0f;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 1000.0f))
{
GameObject objHit = hit.collider.gameObject;
Debug.Log("We Clicked on : " + objHit.name);
//Check if this is cube
if (objHit.CompareTag("Cube"))
{
Debug.Log("Cube selected. You can now drag the Cube with the Slider!");
//Change the current GameObject to drag
currentObjectToDrag = objHit.transform;
}
}
}
}
public void instantiateCube()
{
//Instantiate(cubePrefab, new Vector3(0, 0, 0), Quaternion.identity);
Instantiate(cubePrefab, new Vector3(-15.1281f, 0.67f, 7.978208f), Quaternion.identity);
}
public void rotatess(float newspeed)
{
speed = newspeed;
}
public void positions(float newpos)
{
pos = newpos;
}
//Called when Instantiate Button is clicked
void instantiateButtonCallBack()
{
Debug.Log("Instantiate Button Clicked!");
instantiateCube();
}
//Called when Slider value changes
void sliderCallBack(float value)
{
Debug.Log("Slider Value Moved : " + value);
//Move the Selected GameObject in the Z axis with value from Slider
if (currentObjectToDrag != null)
{
currentObjectToDrag.position = new Vector3(0, 0, value);
Debug.Log("Position changed!");
}
}
//Subscribe to Button and Slider events
void OnEnable()
{
instantiateButton.onClick.AddListener(instantiateButtonCallBack);
cubeSlider.onValueChanged.AddListener(delegate { sliderCallBack(cubeSlider.value); });
}
//Un-Subscribe to Button and Slider events
void OnDisable()
{
instantiateButton.onClick.RemoveListener(instantiateButtonCallBack);
cubeSlider.onValueChanged.RemoveListener(delegate { sliderCallBack(cubeSlider.value); });
}
}
You need to store a reference to the instance you've created.
GameObject myCube = Instantiate(cube, new Vector3(0, 0, 0), Quaternion.identity);
You can then control the position of it using that reference.
myCube.transform.position.x = 10;
Related
my game Item is spawnning behind the spawn button in game i don't know what to do to spawn it in the midddle of the screen:
I made a button just for testing purposes to spawn the potion and here is the code i assigned to it to spawn my item:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HerbSpawner : MonoBehaviour
{
//Here, we declare variables.
public GameObject objToSpawn;
public Transform groupTransform;
//public means the var is exposed in the inspector, which is super helpful.
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//let's also spawn on button press:
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (hit.collider && hit.collider.CompareTag("Bush"))
{
SpawnIt();
}
}
void SpawnIt()
{
//spawn our coin:
Instantiate(objToSpawn, transform.position, Quaternion.identity, groupTransform);
}
}
}
As you want to instantiate it in the middle of the screen,
void SpawnIt()
{
Vector2 spawnPos = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 0.5f));
Instantiate(objToSpawn, spawnPos, Quaternion.identity, groupTransform);
}
Sidenote:
If you are repeatedly spawning in the middle of the screen, cache the spawn position
Vector2 spawnPos;
void Start()
{
spawnPos = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 0.5f));
}
void SpawnIt()
{
Instantiate(objToSpawn, spawnPos, Quaternion.identity, groupTransform);
}
I'm making a 2D game and i have spawning potion items in a making potion scene first of all i want to make the item pop up after spown and go like in this video that i recorded from my game:
Spawned Item do not move like the original
what do i do to make the spawned (Cloned) Item move the same as the original potion item?
Secondly, i want to spawn random and more than one item (potion) each time the scene starts how do i do that knowing that i'm using this script that spawns only one object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HerbSpawner : MonoBehaviour
{
//Here, we declare variables.
public GameObject objToSpawn;
public Transform groupTransform;
//public means the var is exposed in the inspector, which is super helpful.
// Start is called before the first frame update
Vector2 spawnPos;
void Start()
{
spawnPos = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 0.5f));
}
// Update is called once per frame
void Update()
{
//let's also spawn on button press:
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.GetRayIntersection(Camera.main.ScreenPointToRay(Input.mousePosition));
if (hit.collider && hit.collider.CompareTag("Bush"))
{
SpawnIt();
}
}
void SpawnIt()
{
Vector2 spawnPos = Camera.main.ViewportToWorldPoint(new Vector2(0.5f, 0.7f));
Instantiate(objToSpawn, spawnPos, Quaternion.identity, groupTransform);
}
}
}
please let me know if there is anyway to do it spawn multiple objects randomly and make the movement for the items to popup like in the video. This is teh script i used for that:
using System.Collections;
using UnityEngine;
using TMPro;
public class DragNDropItem : MonoBehaviour
{
public string itemName;
private bool dragging;
private Vector2 firstPos;
private Color spriteRenderer;
[SerializeField] private float speed = 3;
[SerializeField] private GameObject boiler;
public TMP_Text itemNameText;
private BoilerScript boilerScript;
public AudioSource drop;
void Awake()
{
// Initial position of the item
firstPos = transform.position;
boiler = GameObject.FindGameObjectWithTag("Boiler");
boilerScript = boiler.GetComponent<BoilerScript>();
spriteRenderer = gameObject.GetComponent<SpriteRenderer>().color;
}
void OnMouseDown()
{
dragging = true;
}
void OnMouseUp()
{
dragging = false;
if (Vector2.Distance(transform.position, boiler.transform.position) < 0.7f) // We control the distance between the item and the cauldron without using the collider.
{
itemNameText.text = itemName;
boilerScript.Potion(); // Checks the recipe's completion status each time an item is placed.
spriteRenderer.a = 0f;
gameObject.GetComponent<SpriteRenderer>().color = spriteRenderer;
StartCoroutine(Alpha());
}
else drop.Play(); // If the item is left
}
void Update()
{
if (dragging) // As soon as the item is clicked with the mouse, the item follows the mouse.
{
Vector2 mousePosition = MousePos();
transform.position = Vector2.Lerp(transform.position, mousePosition, speed * Time.deltaTime);
} else if (!dragging && (Vector2)transform.position != firstPos) // As soon as we stop clicking, it takes it back to its original place. While the item is in its original location, we are constantly preventing the code from running.
{
transform.position = Vector2.Lerp(transform.position, firstPos, speed * Time.deltaTime);
}
}
Vector2 MousePos() // position of mouse
{
return Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
private IEnumerator Alpha() // After a second the item becomes visible.
{
spriteRenderer.a = 1f;
yield return new WaitForSeconds(0.6f);
gameObject.GetComponent<SpriteRenderer>().color = spriteRenderer;
}
}
Your colliders aren't set to trigger. My guess is, when a clone is spawned, it collides with the existing potion object.
So I have UI elements that can be dragged, so that a prefab can be instantiated OnDragEnd(). I am using below code attached to the UI buttons to achieve this
public class MyButton : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
..
..
..
public void OnDrag(PointerEventData eventData)
{
dragRect.anchoredPosition += eventData.delta;
}
public void OnBeginDrag(PointerEventData eventData)
{
// if we're on deploy cooldown, dont allow dragging this button
if (disableDrag )
{
eventData.pointerDrag = null;
}
}
public void OnEndDrag(PointerEventData eventData)
{
RaycastHit hit;
Ray ray = mainCamera.ScreenPointToRay(eventData.pointerCurrentRaycast.screenPosition);
Physics.Raycast(ray, out hit);
if (hit.collider.gameObject.tag == "Ground")
{
createUnit(hit);
disableDrag = true;
}
}
}
This works fine without any problems, but recently I also implemented the ability to drag the camera. I attached the following code to my camera to achieve this:
public class CameraController : MonoBehaviour
{
public float movementTime;
public Vector3 newPosition;
private Vector3 startPosition;
public Vector3 dragStartPosition;
public Vector3 dragCurrentPosition;
public float xLimit1, xLimit2;
float clampedX;
Camera mainCamera;
private void Start()
{
mainCamera = Camera.main;
newPosition = transform.position;
startPosition = transform.position;
}
// Update is called once per frame
void Update()
{
HandleMouseInput();
clampedX = Mathf.Clamp(newPosition.x, xLimit1, xLimit2);
transform.position = Vector3.Lerp(transform.position, new Vector3 (clampedX, startPosition.y, startPosition.z), Time.deltaTime * movementTime);
}
void HandleMouseInput()
{
// when mouse is pressed,
if (Input.GetMouseButtonDown(0))
{
if (!EventSystem.current.IsPointerOverGameObject())
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragStartPosition = ray.GetPoint(entry);
}
}
}
// if it is still held down
if (Input.GetMouseButton(0))
{
if (!EventSystem.current.IsPointerOverGameObject())
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragCurrentPosition = ray.GetPoint(entry);
newPosition = transform.position + dragStartPosition - dragCurrentPosition;
}
}
}
}
}
And the camera script works as well as it behaves as expected and the camera drags with mouse. But the problem is that when I drag my UI button onto screen that moves the camera also.
I tried to include the if condition of checking if its over a UI if (!EventSystem.current.IsPointerOverGameObject()) But this does not seem to work, the camera still drags when I drag the UI button.
How do I make them work together?
You are on the right path as
!EventSystem.current.IsPointerOverGameObject())
is the right way forward, but make sure to use it like this:
// Check if the left mouse button was clicked
if(Input.GetMouseButtonDown(0))
{
// Check if the mouse was clicked over a UI element
if(!EventSystem.current.IsPointerOverGameObject())
{
Debug.Log("Did not Click on the UI");
}
}
Make sure that the RaycastTarget toggle on your UI component is not enabled.
Also, check the Event Mask in the Physics Raycaster on your camera. IsPointerOverGameObject() will return true if the mouse is over any objects on those layers. If you only want to check for the UI layer, make sure that only UI is checked.
Here are some references:
EventSystem.IsPointerOverGameObject Docu.
EventSystem.IsPointerOverGameObject Manual
Thread that might help you
I'm currently making a sandbox game and it is able to create a object through left click. But, I am struggling to destroy a specific object when it is right clicked. I've looked on previous questions here, but they don't exactly answer my question.
using UnityEngine;
using System.Collections;
public class ControlObjects : MonoBehaviour
{
Vector3 mousePosition, targetPosition;
//To Instantiate TargetObject at mouse position
public Transform targetObject;
public GameObject Prefab;
float distance = 10f;
Ray ray;
RaycastHit hit;
//public int item_num = 1;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.position = targetPosition;
//To get the current mouse position
mousePosition = Input.mousePosition;
//Convert the mousePosition according to World position
targetPosition = Camera.main.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, distance));
//Set the position of targetObject
targetObject.position = targetPosition;
//Debug.Log(mousePosition+" "+targetPosition);
//If Left Button is clicked
if (Input.GetMouseButtonDown(0))
{
//create the instance of targetObject and place it at given position.
Instantiate(targetObject, targetObject.transform.position, targetObject.transform.rotation);
}
}
}
Implement what you need, but this is the base.
using UnityEngine;
public class Test : MonoBehaviour
{
private float distance = 10;
private float offset = -4;
void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse1))
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = new Vector3
{
x = offset += 1.5f,
y = 0,
z = 0
};
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Input.GetKeyDown(KeyCode.Mouse0))
{
if(Physics.Raycast(ray, out RaycastHit hit, distance))
{
Destroy(hit.transform.gameObject);
}
}
}
}
You should have a look at IPointerClickHandler. Attach this script to the objects you want to be able to click on
using UnityEngine;
using UnityEngine.EventSystems;
public class DestroyOnRightClick : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick (PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Right)
{
Debug.Log ("Right Mouse Button Clicked on: " + name);
Destroy(gameObject);
}
}
}
Note
Ensure an EventSystem exists in the Scene to allow click detection. For click detection on non-UI GameObjects, ensure a PhysicsRaycaster is attached to the Camera.
EDIT : Apparently when I select Windowed, the buttons work. Why is this? Why doesn't it work without that box selected?
I created a game in Unity and everything works fine in Unity itself. When I build and run the game, my buttons no longer recognize my mouse clicks. Why is this?
This is a basic pong game. I don't know why it would work in Unity and not outside of Unity if it was the code but here is the code.
Code :
paddle script:
using UnityEngine;
using System.Collections;
public class paddle : MonoBehaviour {
public float paddleSpeed = 1;
public Vector3 playerPos = new Vector3(0,0,0);
// Update is called once per frame
void Update () {
float yPos = gameObject.transform.position.y + (Input.GetAxis ("Vertical") * paddleSpeed);
playerPos = new Vector3 (-20,Mathf.Clamp(yPos, -13F,13F),0);
gameObject.transform.position = playerPos;
}
}
ball script:
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
public float ballVelocity = 1500;
private Rigidbody rb;
private bool isPlay; //false by default
int randInt; //random ball directon when game begins
// Use this for initialization
void Awake () {
rb = gameObject.GetComponent<Rigidbody> ();
randInt = Random.Range (1,3);
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButton(0) == true && isPlay == false){
transform.parent = null;
isPlay = true;
rb.isKinematic = false;
if(randInt == 1){
rb.AddForce(new Vector3(ballVelocity,ballVelocity,0));
}
if(randInt == 2){
rb.AddForce(new Vector3(-ballVelocity,-ballVelocity,0));
}
}
}
}
enemy script:
using UnityEngine;
using System.Collections;
public class Enemy : MonoBehaviour {
public float speed = 8;
private Vector3 targetPos;
private Vector3 playerPos;
private GameObject ballObj;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
ballObj = GameObject.FindGameObjectWithTag ("ball");
if (ballObj != null) {
targetPos = Vector3.Lerp (gameObject.transform.position, ballObj.transform.position, Time.deltaTime * speed);
playerPos = new Vector3 (-20, Mathf.Clamp (targetPos.y, -13F, 13F), 0);
gameObject.transform.position = new Vector3 (20, playerPos.y, 0);
}
}
}
score script:
using UnityEngine;
using System.Collections;
public class Score : MonoBehaviour {
public TextMesh currScore;
public GameObject ballPref;
public Transform paddleObj;
GameObject ball;
private int score;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
ball = GameObject.FindGameObjectWithTag("ball");
currScore.text = "" + score;
}
void OnTriggerEnter(Collider other) {
if(other.tag == "ball"){
score += 1;
Destroy(ball);
(Instantiate(ballPref, new Vector3(paddleObj.transform.position.x + 1, paddleObj.transform.position.y,0), Quaternion.identity) as GameObject).transform.parent = paddleObj;
}
}
}
title screen script:
#pragma strict
function Start () {
}
function Update () {
}
function StartGame () {
Application.LoadLevel("Main");
}
function ExitGame () {
Application.Quit();
}
From what I am understanding, you want Unity to recognize your mouse button event even when the mouse pointer is not inside the game Window.
There could be 2 ways to achieve this:
1. The easy way, make your game full screen.
2. If you want your game in a window box, you must check "Run In Background" option in Player settings -> Resolution. And then, learn how to hook mouse event: http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C
Please note that the hooking mouse event tutorial only works on Windows, not Mac nor Linux. I do not know how to do it with Mac or Linux.