I am doing a 2D project where I've added a sprite as a button to shoot. This button works fine. The script attached is: (I added a box collider to the sprite)
using UnityEngine;
using System.Collections;
public class ClickScript : MonoBehaviour {
public shootTest _shooterScript;
// Use this for initialization
void Start () {
}
void LoadScript()
{
_shooterScript.ShootRock();
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0)){
Vector2 mousePosition = new Vector2();
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Collider2D hitCollider = new Collider2D();
hitCollider = this.collider2D;
hitCollider = Physics2D.OverlapPoint(mousePosition);
Debug.Log("mouse pos "+mousePosition.x+" y "+mousePosition.y+" ");
if(hitCollider){
LoadScript();
Debug.Log("Hit "+hitCollider.transform.name+" x"+hitCollider.transform.position.x+" y "+hitCollider.transform.position.y);
}
}
}}
Then I added a crosshair to be able to calculate a direction to aim. Here is the script to click and drag the object. Circle Colider 2D on this object.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(MeshCollider))]
public class Aim : MonoBehaviour
{
private Vector3 screenPoint;
private Vector3 offset;
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position);
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnMouseDrag()
{
Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint)+offset;
this.transform.position = curPosition;
}
}
When I add this aiming script and click on the crosshair to drag it, the shoot script goes off.
I'm very new to unity so I'm assuming it is something simple. Thanks for the help.
I changed the update function in the click script to
void Update () {
if(Input.GetMouseButtonDown(0)){
Vector2 mousePosition = new Vector2();
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(this.collider2D.OverlapPoint(mousePosition)){
LoadScript();
}
}
So it only triggers when that specific object is clicked. Maybe there is a cleaner way, but this worked.
Related
I wanted to recreate a game (tangram) where you can rotate and move the pieces.
The game can be found on this website: https://de.mathigon.org/tangram
I have found scripts for rotating and moving the object (a png-file) but when I add the two scripts togehter the object moves randomly around. As programme I use Unity.
The script for moving:
using UnityEngine;
using System.Collections;
public class DragDropScript : MonoBehaviour {
private Vector3 screenPoint;
private Vector3 offset;
void OnMouseDown()
{
Debug.Log("mouse down");
screenPoint = Camera.main.WorldToScreenPoint(transform.position);
offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnMouseDrag()
{
Debug.Log("mouse drag");
Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;
transform.position = curPosition;
}
}
And the script for rotating
using UnityEngine;
using System.Collections;
public class ObjectRotator : MonoBehaviour
{
private float _sensitivity;
private Vector3 _mouseReference;
private Vector3 _mouseOffset;
private Vector3 _rotation;
private bool _isRotating;
void Start ()
{
_sensitivity = 0.4f;
_rotation = Vector3.zero;
}
void Update()
{
if(_isRotating)
{
// offset
_mouseOffset = (Input.mousePosition - _mouseReference);
// apply rotation
_rotation.z = -(_mouseOffset.x + _mouseOffset.y) * _sensitivity;
// rotate
transform.Rotate(_rotation);
// store mouse
_mouseReference = Input.mousePosition;
}
}
void OnMouseDown()
{
// rotating flag
_isRotating = true;
// store mouse
_mouseReference = Input.mousePosition;
}
void OnMouseUp()
{
// rotating flag
_isRotating = false;
}
}
So far I struggle with Unity. In my bachelor-thesis I got a HoloLens2 and could use the MRTK which really helped developing a application. Thank you in advanced.
At the end the game should be built as WebGL.
The random result is probably due to trying to move and rotate the object at the same time. An easy fix for this would be to move on left mouse button and rotate with right click, or vice versa. You can use Input.GetMouseButton to check if a button is pressed and insert checks in the script to only move OR rotate.
More complicated solutions would involve some kind of "widget" that is dragged, that way you can have different widgets for drag and rotate.
I would also recommend learning a bit of geometry and trigonometry to be able to understand the posted scripts. Copying scripts of the internet will only get you so far.
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.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour {
public GameObject player;
public GameObject arrow;
private Vector3 a;
private float angle;
private Rigidbody2D rb2D;
void Start()
{
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
a = Input.mousePosition;
Vector2 difference = a - player.transform.position;
GameObject Aprefab = Instantiate(arrow) as GameObject;
rb2D = Aprefab.GetComponent<Rigidbody2D>();
rb2D.AddForce(difference * 0.02f, ForceMode2D.Impulse);
}
angle = Mathf.Atan2(rb2D.velocity.y, rb2D.velocity.x);
Aprefab.transform.localEulerAngles = new Vector3(0, 0, (angle * 180) / Mathf.PI);
}
}
Currently, I am making an arrow shooter.
I want to set arrow heading continuously while flying.
so I need to access "Aprefab" GameObject out of if block.
but how?
Need some help
To expand upon my comment: I've
refactored the shooting stuff into another function
added a list arrows to keep track of all the arrows fired (that Shoot() adds to)
made Update() iterate over all the arrows and update them
I don't have Unity at present, and this is dry-coded, so there might be some bugs.
Also, you'll want to take care of cleaning stuff up from the arrows list at some point.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour {
public GameObject player;
private List<GameObject> arrows = new List<GameObject>();
void Start()
{
}
void Update () {
if (Input.GetMouseButtonDown(0))
{
Shoot();
}
foreach(var arrow in arrows) {
var rb2D = Aprefab.GetComponent<Rigidbody2D>();
var angle = Mathf.Atan2(rb2D.velocity.y, rb2D.velocity.x);
arrow.transform.localEulerAngles = new Vector3(0, 0, (angle * 180) / Mathf.PI);
}
}
private void Shoot() {
var a = Input.mousePosition;
var difference = a - player.transform.position;
var Aprefab = Instantiate(arrow) as GameObject;
var rb2D = Aprefab.GetComponent<Rigidbody2D>();
rb2D.AddForce(difference * 0.02f, ForceMode2D.Impulse);
arrows.Add(Aprefab);
}
}
I have 2D mesh in the XY plane. I have the following script which moves the camera across the plane, the camera starts at (0,0,-10).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragMap : MonoBehaviour {
private float dist;
private Vector3 MouseStart;
private Vector3 derp;
void Start () {
dist = transform.position.z; // Distance camera is above map
}
void Update () {
if (Input.GetMouseButtonDown (2)) {
MouseStart = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
MouseStart = Camera.main.ScreenToWorldPoint (MouseStart);
MouseStart.z = transform.position.z;
}
else if (Input.GetMouseButton (2)) {
var MouseMove = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
MouseMove = Camera.main.ScreenToWorldPoint (MouseMove);
MouseMove.z = transform.position.z;
transform.position = transform.position - (MouseMove - MouseStart);
}
}
}
But I cannot for the life of me figure out what to change so that if I drag my mouse to the right, the camera goes to the left and vice versa. Similarly if I drag my mouse up I want to move the camera down and vice versa. Help!
Thank you for any replies.
-DrOmega.
You need to negate the x of the MouseMove vector to only flip the x movement:
MouseMove = new Vector3(-MouseMove.x, MouseMove.y, MouseMove.z);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragMap : MonoBehaviour {
private float dist;
private Vector3 MouseStart;
private Vector3 derp;
void Start () {
dist = transform.position.z; // Distance camera is above map
}
void Update () {
if (Input.GetMouseButtonDown (2)) {
MouseStart = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
MouseStart = Camera.main.ScreenToWorldPoint (MouseStart);
MouseStart.z = transform.position.z;
}
else if (Input.GetMouseButton (2)) {
var MouseMove = new Vector3(Input.mousePosition.x, Input.mousePosition.y, dist);
MouseMove = Camera.main.ScreenToWorldPoint (MouseMove);
MouseMove.z = transform.position.z;
transform.position = transform.position - (MouseMove - MouseStart);
}
}
}
there is an easy fix here. if you want to flip both the x and the y, replace "- (MouseMove - MouseStart)" with "+ (MouseMove - MouseStart)"
So I have a button in my game which spawns a "tower" at a given location. The tower, when spawned, acts normally and I can drag it around using my drag script.
I wonder how can I set the Time.timeScale to 0 when I first spawn the tower (only for that prefab) UNTILL I click again to set it's position.
Also after the click on the button I want to enable my dragging script, set the position and after another click with the mouse to disable the dragging script. That way I can make sure players don't reposition towers for extra damage.
using UnityEngine;
using System.Collections;
public class SpawnTower : MonoBehaviour {
public GameObject FrozenObject;
public Transform prefab;
public void OnClickSpawn()
{
for (int i = 0; i < 1; i++)
{
Instantiate(prefab, new Vector3(i * 2.0F, 0, 0), Quaternion.identity);
}
}
//this part from here on DOES NOT WORK! It says that the GetComponent<>() method that is not valin in the given context
public void OnClick()
{
if (Input.GetMouseButtonUp(0))
{
GetComponent<DragEnemy>.enabled = false;
}
}
}
Note the part that doesn't work
And this is my dragging script which for some reason can't be referenced to be disabled.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(BoxCollider2D))]
public class DragEnemy : MonoBehaviour
{
private Vector3 screenPoint;
private Vector3 offset;
void OnMouseDown()
{
offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
void OnMouseDrag()
{
Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;
transform.position = curPosition;
}
}