I created 9 clone objects and U use OnMouseDrag function to move my objects.
First I drag object in the area zone and left button click to placed it in the map.
void OnMouseDrag(){
if(placed==false && placedArmyCounter<3){
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mousePos.z = 0f;
mousePos.x=Mathf.Round(mousePos.x);
mousePos.y=Mathf.Round(mousePos.y);
if( BoardManager.boardID==0 && mousePos.x>=0 && mousePos.x<=5 && mousePos.y>=0 && mousePos.y<=2){
transform.position=new Vector2((mousePos.x),(mousePos.y));
}
if( BoardManager.boardID==1 && mousePos.x>=0 && mousePos.x<=7 && mousePos.y>=0 && mousePos.y<=3){
transform.position=new Vector2((mousePos.x),(mousePos.y));
}
}
}
Left click
if(Input.GetMouseButtonDown(1) )
{
RaycastHit2D hit = Physics2D.Raycast (Camera.main.ScreenToWorldPoint((Input.mousePosition)), -Vector2.up);
if(hit.collider != null)
{
GameObject target = hit.collider.gameObject;
if(target.tag=="infantry"){
target.GetComponent<playerArmyMove>().Place();
}
if(target.tag=="archer"){
target.GetComponent<playerArmyMove>().Place();
}
if(target.tag=="horseman"){
target.GetComponent<playerArmyMove>().Place();
}
}
}
place function
public void Place(){
if(checkPlace==true){
placed=false;
}
if(checkPlace==false){
placed=true;
placedArmyCounter+=1;
}
}
When placed is true object cannot move again and placedArmyController using for starting game
By the way, I want only 3 objects can place in map area.
But there is a problem if I don't click left button , I can add a lot of objects in the map.And I don't want to happen like that.
I know I need another controller which checks "is there any object in map area and is placed or not".But if I add the controller in OnMouseDrag function any object can not move.
Is there any suggestion?
P.S : Don't care checkPlace boolean in place function it is about detect collision.
Related
I am creating an AR application with Unity. In this application, I want to place an object on the detected planes from AR.
void Update()
{
if (Input.touchCount > 0)
{
PlaceObject(Input.GetTouch(0).position);
}
}
public void PlaceObject(Vector2 touchPosition)
{
if (m_RaycastManager.Raycast(touchPosition, s_Hits, TrackableType.PlaneWithinPolygon))
{
var hitPose = s_Hits[0].pose;
if (spawnedObject == null)
{
spawnedObject = Instantiate(m_PlacedPrefab, hitPose.position, hitPose.rotation);
}
else
{
spawnedObject.transform.position = hitPose.position;
}
}
}
If I use touch input (clicking on the detected plane) it works fine and object will be placed on the plane.
When I try to call PlaceObject function with the same touchPosition from another controller, ARRaycastManager.Raycast return false and it didn't found any hit objects.
How to make ARRaycastManager.Raycast returns hit objects when called from function and not from input touch?
I have scripted a controller for opening doors in a TopDown-Shooter.
I rotate pivot points around their local Y-Axis to open the door objects. The doors should stay open, so I do not need the Controller and the Controller object anymore. I want to destroy it after finishing its job.
My script looks this:
public class DoorController : MonoBehaviour
{
public Transform pivotLeftTransform; // the left pivot point
public Transform pivotRightTransform; // the right pivot point
int openAngle = 90; // how far should the door open up?
bool startOpen = false; // start opening?
float smooth = 2; // smooth rotation
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
startOpen = true; // when the Player triggers, start opening
}
}
void Update()
{
if (startOpen)
{
OpenDoor(pivotLeftTransform, openAngle);
OpenDoor(pivotRightTransform, -openAngle);
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle) // when the doors are rotated, destroy this object
{
Destroy(gameObject);
}
}
}
private void OpenDoor(Transform pivotTransform, int rotationAngle)
{
Quaternion doorRotationOpen = Quaternion.Euler(0, rotationAngle, 0); // desired door rotation
pivotTransform.localRotation = Quaternion.Slerp(pivotTransform.localRotation, doorRotationOpen, smooth * Time.deltaTime); // rotate the door to the desired rotation
}
}
My Question is, how can I destroy the object. My code
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle)
does not seem to work. After having the pivot point rotated to 90 or -90 degrees the statement still stays false. I also tried
pivotTransform.rotation.y
but it does not work neither. Which rotation do I need to pass in?
Thanks.
Two things wrong in your code:
1.Comparing floats
2.Using transform.localRotation or transform.rotation to check for angle.
You can solve this by using eulerAngles or localEulerAngles. Also for comparing floats, use >= instead of = as that may never be true.
Replace
if (pivotLeftTransform.localRotation.y == openAngle && pivotRightTransform.localRotation.y == -openAngle)
{
Destroy(gameObject);
}
with
if (pivotLeftTransform.localEulerAngles.y >= openAngle && pivotRightTransform.localRotation.y >= -openAngle)
{
Destroy(gameObject);
}
If you have problem with the answer above you have to troubleshoot it one by one. Separate the && and see which one is failing like this:
if (pivotLeftTransform.localEulerAngles.y >= openAngle)
{
Debug.Log("pivotLeftTransform");
}
if (pivotRightTransform.localRotation.y >= -openAngle)
{
Debug.Log("pivotRightTransform");
}
The right way to archieve this is adding a small tolerance value:
if (pivotLeftTransform.localEulerAngles.y >= openAngle - 0.1f && pivotRightTransform.localEulerAngles.y <= 360 - openAngle + 0.1f)
This may not be code clean but it works for the moment :)
I have this script where it would add the SelectMove script at runtime when a character was touched by the user.
public GameObject target;
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.touchCount > 0 || Input.GetTouch(0).phase == TouchPhase.Began){
ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
Debug.DrawRay(ray.origin,ray.direction * 20,Color.red);
if(Physics.Raycast(ray, out hit,Mathf.Infinity)){
Debug.Log(hit.transform.gameObject.name);
target = hit.transform.gameObject;
//Destroy(hit.transform.gameObject);
selectedPlayer();
}
}
}
void selectedPlayer(){
target.AddComponent(Type.GetType("SelectMove"));
}
In the code above, if the user will click Player A, Player A will move using accelerometer. What I need to do is if I click another character, say Player B, I need Player A to stop moving and it is now Player B's time to move. But I seemed not to get what I want. I tried destroying the script by using Destroy(this) or by this code:
if (target != null)
{
var sphereMesh = target.GetComponent<SelectMove>();
Destroy(sphereMesh);
}
But it is still not working.
If I don't destroy the previous added script, if the user clicks for another character, the previous selected player still moves along with the new one.
Is there another way that I could achieve what I needed to do?
public GameObject target = null;
void Update ()
{
if(Input.touchCount > 0 || Input.GetTouch(0).phase == TouchPhase.Began)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
Debug.DrawRay(ray.origin,ray.direction * 20,Color.red);
RaycastHit hit;
if(Physics.Raycast(ray, out hit,Mathf.Infinity))
{
Debug.Log(hit.transform.gameObject.name);
if(this.target != null){
SelectMove sm = this.target.GetComponent<SelectMove>()
if(sm != null){ sm.enabled = false; }
}
target = hit.transform.gameObject;
//Destroy(hit.transform.gameObject);
selectedPlayer();
}
}
}
void selectedPlayer(){
SelectMove sm = this.target.GetComponent<SelectMove>();
if(sm == null){
target.AddComponent<SelectMove>();
}
sm.enabled = true;
}
The code reuses your base, the new part is that you use the previous selected object to disable the SelectMove script (I assume it is the one moving things). Instead of destroying it, it enables/disables so you save that memory consumption.
I do not think Adding and destroying scripts is the convenient method here.
Try this:
1. Add the SelectMove script to all movable players.
2. Add a public property bool IsMoving = false; to the SelectMove script and make an if statement to move if IsMoving is true.
3. Change selectedPlayer() method to instead change the target player IsMoving to true, and set the previous one (or simply all other players) to false.
I am making a pokemon clone.
It is a top down tile based rpg.
So I added 4 gameobjects on the player itself. Called up, down, left, right.
I placed them around the player. I use this set up to check if the gameObject up. Is standing on water. If that is true then the player cannot go up. It is my work around for collision. However my children don't want to follow my parent. All I did was I dragged the 4 for gameobjects onto the player, and added this c# script:
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
public LayerMask GroundLayer;
Vector2 startPoint;
Vector2 endPoint;
private float increment;
bool isMoving;
public float speed;
public tk2dTileMap tilemap;
public GameObject up;
public GameObject down;
public GameObject left;
public GameObject right;
void Start()
{
startPoint = transform.position;
endPoint = transform.position;
}
void Update()
{
if (increment <= 1 && isMoving == true)
{
increment += speed / 100;
}
else
{
isMoving = false;
}
if (isMoving)
{
transform.position = Vector2.Lerp(startPoint, endPoint, increment);
}
if (Input.GetKey(KeyCode.UpArrow) && isMoving == false)
{
if (MovementEvents(up) == 0)
{
move(up);
}
}
else if (Input.GetKey(KeyCode.DownArrow) && isMoving == false)
{
if (MovementEvents(down) == 0)
{
move(down);
}
}
else if (Input.GetKey(KeyCode.LeftArrow) && isMoving == false)
{
if (MovementEvents(left) == 0)
{
move(left);
}
}
else if (Input.GetKey(KeyCode.RightArrow) && isMoving == false)
{
if (MovementEvents(right) == 0)
{
move(right);
}
}
}
int MovementEvents(GameObject direction)
{
switch (tilemap.GetTileIdAtPosition(direction.transform.position, 0)) //gettileIdAtPosition returns the id of a tile in this case 0 is grass and 1 is water
{
case 0:
return 0;
default:
return 1;
}
}
void move(GameObject direction)
{
increment = 0;
isMoving = true;
startPoint = transform.position;
endPoint = direction.transform.position;
}
}
I am using 2d toolkit.
I know it is probaly because i am setting them in the wrong way but what am i doing wrong?
You are creating new GameObjects in your script (up, down, etc.) that have no relation to the objects you created in the editor. There are two solutions to this:
1) You need to assign up, down, etc. to the GameObjects you created in the editor. You can do this by editing your Start method to include:
up = GameObject.Find( "up" );
down = GameObject.Find( "down" );
// etc.
Replacing "up" with whatever you named the up GameObject in the editor.
2) Assign up, down, etc. as children to your parent GameObject using
up.transform.parent = parentGameObject.transform;
down.transform.parent = parentGameObject.transform;
// etc.
Note that if you go this route, then the up, down, etc. objects you made in the editor will not be used. You also will need to translate the new objects (after setting their parent) or else they will just sit at (0,0,0) relative to the parent.
Edit in response to the comments
If I am understanding the problem correctly, then it seems you are just making a mistake in how you add the up, down, etc. objects as children in the editor. Simply drag them all onto the parent at the same level:
Then whenever the TestParent object moves, the other objects stay at the same relative position to the parent, and thus move as well. Then if you add the GameObjects to a script like so:
You can move the objects individually (while still being relative to the parent). With the following example script, the parent object moves up (Y+) at one unit a second. The Down object also moves up at an additional one unit per second. This results in the ParentTest, Up, Left, Right maintaining formation, moving one unit per second up, while Down moves at two units per second and slowly moves past them.
using UnityEngine;
using System.Collections;
public class DeleteMe : MonoBehaviour
{
public GameObject Up;
public GameObject Down;
public GameObject Left;
public GameObject Right;
void Start( )
{
}
// Update is called once per frame
void Update( )
{
Move( gameObject );
Move( Down );
}
private void Move( GameObject obj )
{
Vector3 position = obj.transform.position;
position.y += UnityEngine.Time.deltaTime;
obj.transform.position = position;
}
}
A screenshot of them at the start:
Another after some time has elapsed:
Finally note that you do not need to have public GameObjects in the script and then drag-and-drop them onto the script to access children. The same result can be achieved by modifying the script to:
private GameObject Up;
private GameObject Down;
private GameObject Left;
private GameObject Right;
void Start( )
{
Up = transform.Find( "Up" ).gameObject;
Down = transform.Find( "Down" ).gameObject;
Left = transform.Find( "Left" ).gameObject;
Right = transform.Find( "Right" ).gameObject;
}
This prevents the tedious nature of having to drag-and-drop onto the script itself, and also allows you to access children that may be added to the parent dynamically, and thus unable to drag-and-drop.
Hope this has helped!
I have tried every which way possible to get this to work with no success. I have a swipe script and a game/control script. I am trying to reference the swipe control in my control script as the means to control my character. So far I am getting only one error from within Unity.
Assets/RuinRunStarterKit/Scripts/csTempleRun.cs(307,25): error CS1501: No overload for method UpdatePlayer' takes0' arguments
I've tried adding TouchDetector.enTouchType within the parenthesis of UpdatePlayer but that gives me three errors rather than just one. I've contacted numerous people and visited numerous sites looking for answers but have failed to yield a working result. I am not educated in programming. I have only researched online to figure out how to do something as far as programming goes. The second script I have here is from an Asset I purchased on the Unity Asset Store. I have contacted them for support for adding swipe controls and they emailed me the touch script but failed to tell me how to implement it. I just want to play this game on my phone with swipe as the controls. This is for personal use. I would really really appreciate it if someone could help me achieve the desired results. Again, I want to be able to control the character using swipe. Thank you. Here are my scripts:
TouchDetector.cs;
using UnityEngine;
using System.Collections;
public class TouchDetector : MonoBehaviour {
public delegate void deTouchEvent
(enTouchType touchType);
public static event
deTouchEvent
evTouchEvent;
public enum enTouchType
{
SwipeLeft,
SwipeRight,
SwipeDown,
SwipeUp,
}
void Start ()
{
}
void Update ()
{
if (evTouchEvent == null)
return;
if (Input.GetKeyDown(KeyCode.UpArrow )) evTouchEvent(enTouchType.SwipeUp );
if (Input.GetKeyDown(KeyCode.DownArrow )) evTouchEvent(enTouchType.SwipeDown );
if (Input.GetKeyDown(KeyCode.LeftArrow )) evTouchEvent(enTouchType.SwipeLeft );
if (Input.GetKeyDown(KeyCode.RightArrow)) evTouchEvent(enTouchType.SwipeRight);
if (Input.touchCount > 0)
{
foreach (Touch t in Input.touches)
{
Vector3 swipe = t.deltaPosition * t.deltaTime;
if (swipe.y > 0.5f) evTouchEvent(enTouchType.SwipeUp );
if (swipe.y < -0.5f) evTouchEvent(enTouchType.SwipeDown );
if (swipe.x > 0.5f) evTouchEvent(enTouchType.SwipeRight);
if (swipe.x < -0.5f) evTouchEvent(enTouchType.SwipeLeft );
}
}
}
}
csTempleRun.cs;
void Update ()
{
UpdatePlayer();
if (m_player != null)
{
// Make the camera follow the player (if active)
SmoothFollow sF = (SmoothFollow)Camera.mainCamera.GetComponent(typeof(SmoothFollow));
sF.target = m_player.transform;
// Check for collisions with interactive objects
UpdateCoins();
UpdateMines();
// Dynamically update the track
CreateNewCellsIfNeeded(false);
}
}
private void UpdatePlayer(TouchDetector.enTouchType T)
{
// if the player is dead (replaced with ragdoll) then exit since none of this code should fire.
if (m_player == null)
{
return;
}
// Gradually increase the players' running speed, and update the animation to match.
m_playerRunSpeed += Time.deltaTime * 0.005f;
m_playerRunSpeed = Mathf.Clamp(m_playerRunSpeed, 0.5f, 3.0f);
m_player.animation["run"].speed = m_playerRunSpeed * 2.0f;
// ****************************************************************************************
// INPUT
// Player can only turn if they are not already sliding / jumping.
// Equally, sliding / jumping are mutually exclusive.
if (Input.GetKeyDown (KeyCode.LeftArrow)&& m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
if (m_playerDirection == enCellDir.North) m_playerNextDirection = enCellDir.West;
if (m_playerDirection == enCellDir.East ) m_playerNextDirection = enCellDir.North;
if (m_playerDirection == enCellDir.South) m_playerNextDirection = enCellDir.East;
if (m_playerDirection == enCellDir.West ) m_playerNextDirection = enCellDir.South;
}
if (Input.GetKeyDown(KeyCode.RightArrow) && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
if (m_playerDirection == enCellDir.North) m_playerNextDirection = enCellDir.East;
if (m_playerDirection == enCellDir.East ) m_playerNextDirection = enCellDir.South;
if (m_playerDirection == enCellDir.South) m_playerNextDirection = enCellDir.West;
if (m_playerDirection == enCellDir.West ) m_playerNextDirection = enCellDir.North;
}
if (T==TouchDetector.enTouchType.SwipeDown && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
m_playerSlide = 1.0f;
m_player.animation.Play("slide_fake");
}
if ((Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space)) && m_playerJump <= -1.0f && m_playerSlide <=0.0f)
{
AudioSource.PlayClipAtPoint(m_jumpAudio, m_player.transform.position);
m_playerJump = 1.0f;
m_playerYvel = 0.0f;
m_player.animation.Play("jump");
}
I hope I'm not doing anything wrong by posting this script but I feel I need to post this in order to get the help I need. You'll notice in the csTempleRun.cs script that I replaced one of the KeyCode calls with TouchDetector.enTouchType.SwipeDown. Yet I am still getting an error. Thank you in advance for anyone's help. Thank you for your time as well.
Look at your error - No overload for method UpdatePlayer' takes0' arguments. It means that you need to supply an additional data to your method. Which data you need to supply intellisense can tell you.
In your code:
void Update ()
{
UpdatePlayer();
...
You call UpdatePlayer() with zero arguments. However, UpdatePlayer needs an argument:
private void UpdatePlayer(TouchDetector.enTouchType T)
{
So, when you call UpdatePlayer(), you need to send an object of the type TouchDetector.enTouchType as parameter. That would be one of the following:
SwipeLeft
SwipeRight
SwipeDown
SwipeUp