How to create an array for UI elements with children in unity - c#

I am trying to make a system for when you press a button it instantiates a random card for a card game, but I can't figure out how to create an array for the cards (the cards are just ui images with some text on them (the image being a parent)) although using the refrence "Gameobject" although since the cards are ui elements not acctual game objects it didn't work so i tried using the refrence "Image" but then it only instantiated the actual image part. - pls help i know its a bit confusing but if u can help pls do i have only been programming for just over a year now so i am not very good with problems like this /:
code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CardMasterScript : MonoBehaviour
{
public Image[] CardArray = new Image[8];
public float RollNumber;
public Canvas ParentCanvas;
public void RollCard()
{
RollNumber = Random.Range(0.1f, 100);
Debug.Log("Number Rolled: " + RollNumber);
if(RollNumber <= 47.9)
{
var card = Instantiate(CardArray[0]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if(RollNumber > 47.9 && RollNumber <= 77.9)
{
var card = Instantiate(CardArray[1]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if( RollNumber > 77.9 && RollNumber <= 87.9)
{
var card = Instantiate(CardArray[2]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if(RollNumber > 87.9 && RollNumber <= 94.9)
{
var card = Instantiate(CardArray[3]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if(RollNumber > 94.9 && RollNumber <= 97.9)
{
var card = Instantiate(CardArray[4]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if(RollNumber > 97.9 && RollNumber <= 99.4)
{
var card = Instantiate(CardArray[5]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if(RollNumber > 99.4 && RollNumber <= 99.9)
{
var card = Instantiate(CardArray[6]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
} else if (RollNumber > 99.9 && RollNumber <= 100)
{
var card = Instantiate(CardArray[7]);
card.transform.SetParent(ParentCanvas.transform);
Destroy(card, 0.5f);
}
}
}
Thank you in advance!
i have tried changing the refrence in the array to image, i expected unity to just instantiate the image and its children aswell but it only instantiated the image.

I don't see why you can't create 8 GameObjects that have an image attached to them and have your CardArray be a GameObject array instead. Also the Instantiate function may have a transform argument to set its parent to.
For instance you can replace
var card = Instantiate(CardArray[0]);
card.transform.SetParent(ParentCanvas.transform);
by
var card = Instantiate(CardArray[0], ParentCanvas.transform);
An Image alone doesn't have any children, it needs to be attached to an object that has some. That is why you can't instantiate an Image and expect it to have children
Hope that helps,

Related

Player randomly changing position after implementing UI elements

So I've been following a tutorial on making a 2D game in Unity (I'm a complete newbie, this is my first contact with programming), and I wanted to add a feature to the game(bold).
The "heart system" that I added works correctly (the number of empty hearts is equal to damage taken by player), but it caused my player to transform his position in a wierd way. You can see, that there are boundries set (maxHeight =3,2, minHeight=-3,2), and the value of his movement as well (Yincrement = 3.2) and yet, after pressing up or down arrowkeys he seems to change Y position by around 4.67.
Here's the player script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
private Vector2 targetPos;
public float Yincrement;
public float speed;
public float maxHeight;
public float minHeigth;
public int health = 3;
public int numOfHearts;
public Image[] hearts;
public Sprite heartFull;
public Sprite heartEmpty;
public GameObject effect;
public Image healthDisplay;
private void Update()
{
for (int i = 0; i < hearts.Length; i++)
{
if (i < health)
{
hearts[i].sprite = heartFull;
}
else
{
hearts[i].sprite = heartEmpty;
if (i < numOfHearts)
{
hearts[i].enabled = true;
}
else
{
hearts[i].enabled = false;
}
}
if (health <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.UpArrow) && transform.position.y < maxHeight)
{
Instantiate(effect, transform.position, Quaternion.identity);
targetPos = new Vector2(transform.position.x, transform.position.y + Yincrement);
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && transform.position.y > minHeigth)
{
Instantiate(effect, transform.position, Quaternion.identity);
targetPos = new Vector2(transform.position.x, transform.position.y - Yincrement);
}
}
}
}
Main Issue
The main problem is your for loop. It should only be used for updating the UI - not for multiple times calling your movement and Scene reload! You should close your for loop earlier.
for (int i = 0; i < hearts.Length; i++)
{
// you can also reduce these to single lines
hearts[i].enabled = i < numOfHearts;
if(i < numOfHearts) hearts[i].sprite = i < health ? heartFull : heartEmpty;
} // <-- ALREADY CLOSE IT HERE
if(health <= 0) ...
...
Position clamping
Your clamping of the position is extremely insecure! Imagine the current position being 3.1 which is still < maxHeight so you add the Yincrement once and it results in a maximum possible height of 6.3! That's not what you wanted.
You should clamp directly on the targetPosition not on the current transform.position. You could for example use Mathf.Clamp for making sure the targetPos.y always stays within the given range.
Also since both cases do something very similar I would reduce this to only one movement using a simply int variable for setting the direction:
...
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
var move = 0;
var targetPosY = targePos.y;
if (Input.GetKeyDown(KeyCode.UpArrow) && targetPosY < maxHeight)
{
move = 1;
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && targetPosY > minHeigth)
{
move = -1;
}
// Handle the movement according to the direction
// in one single code block for both directions
if(move != 0)
{
Instantiate(effect, transform.position, Quaternion.identity);
// increase/decrease the targetPosY according to the move direction
targetPosY += move * Yincrement;
// Now make sure it is within the range
targetPosY = Mathf.Clamp(targetPosY, minHeight, maxHeight);
// finally assign the new target position
targetPos = new Vector2(transform.position.x, targetPosY);
}
Could you please specify in detail what your game is about and what you are trying to do in each part of the script. I might be able to help you then. Also, if this is your first contact with programming, this is way to advanced. Start with something simpler and first understand the basic concepts of programming before moving on. Here is a good tutorial series to learn c# programming for absolute beginners.
https://www.youtube.com/watch?v=pSiIHe2uZ2w
I am not sure what you are trying to do but why is your movement control within your for loop. That might be why your are messing up. Try removing all of this code out of the for loop.
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.UpArrow) && transform.position.y < maxHeight)
{
Instantiate(effect, transform.position, Quaternion.identity);
targetPos = new Vector2(transform.position.x, transform.position.y + Yincrement);
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && transform.position.y > minHeigth)
{
Instantiate(effect, transform.position, Quaternion.identity);
targetPos = new Vector2(transform.position.x, transform.position.y - Yincrement);
}
Also this code should be after you check if the player has moved.
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
Here is a tip to make movement a little easier. Use transform.translate instead of Vector2.MoveTowards. Transform.translate takes in 3 floats and changes you player's position by the three floats represented as a vector.
Here is an example
transform.translate(0,2,0);
This will change the players y position by 2. I thing your code should look like this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
private Vector2 targetPos;
public float Yincrement;
public float speed;
public float maxHeight;
public float minHeigth;
public int health = 3;
public int numOfHearts;
public Image[] hearts;
public Sprite heartFull;
public Sprite heartEmpty;
public GameObject effect;
public Image healthDisplay;
private void Update()
{
for (int i = 0; i < hearts.Length; i++)
{
if (i < health)
{
hearts[i].sprite = heartFull;
}
else
{
hearts[i].sprite = heartEmpty;
if (i < numOfHearts)
{
hearts[i].enabled = true;
}
else
{
hearts[i].enabled = false;
}
}
}
if (health <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
if (Input.GetKeyDown(KeyCode.UpArrow) && transform.position.y < maxHeight)
{
transform.Translate(0,Yincrement,0)
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && transform.position.y > minHeigth)
{
Instantiate(effect, transform.position, Quaternion.identity);
transform.Translate(0,Yincrement,0);
}
}
}
After I receive your reply, I possibly could help but there are no guarantees because I only have about a years worth of experience too.

Dynamically create a plane between 4 known points in Unity ARCore for Android

I am trying to dynamically create a plane between 4 known points. The 4 points are created by the user touching the phone screen and a cylinder is placed where they touched, very similar to HelloAR tutorial except with cylinders and not Andys. This is working, the 4 cylinders get created. In a hypothetical situation the user is going to create a square with the 4 points, let's say 2 meters by 2 meters. I then want to dynamically place a plane that fits into the 4 points (it doesn't have to fit exactly, just roughly). Using adb I have validated that the CreateBricks method is called and the plane is instantiated with the correct transform. I just don't see the plane get created.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using GoogleARCore;
public class SceneController : MonoBehaviour {
public Camera firstPersonCamera;
public Text anchorcount;
public GameObject pointPrefab; //The cylinder prefab
public GameObject patioPrefab; //The plane prefab
public ArrayList pointArray;
private int anchorCount;
private bool m_IsQuitting = false;
private bool brickCreated = false;
// Use this for initialization
void Start () {
QuitOnConnectionErrors();
anchorCount = 0;
pointArray = new ArrayList();
brickCreated = false;
}
// Update is called once per frame
void Update () {
_UpdateApplicationLifecycle();
if (anchorCount < 4)
ProcessTouches();
else if(!brickCreated)
CreateBricks();
}
private void CreateBricks()
{
try
{
brickCreated = true;
Debug.Log("CreateBricks");
float dist1 = Vector3.Distance(((GameObject)pointArray[0]).transform.position, ((GameObject)pointArray[1]).transform.position);
float dist2 = Vector3.Distance(((GameObject)pointArray[0]).transform.position, ((GameObject)pointArray[3]).transform.position);
Debug.Log("dist1:" + dist1.ToString());
Debug.Log("dist2:" + dist2.ToString());
GameObject prefab;
prefab = patioPrefab;
// Instantiate Andy model at the hit pose.
var pointObject = Instantiate(prefab);
prefab.transform.position = ((GameObject)pointArray[0]).transform.position;
prefab.transform.position.Scale(new Vector3(dist1, 0.5f, dist2));
Debug.Log(prefab.transform.position.x.ToString() + " " + prefab.transform.position.y.ToString() + " " + prefab.transform.position.z.ToString());
}
catch (System.Exception ex)
{
Debug.Log(ex.Message);
}
}
void ProcessTouches()
{
Touch touch;
if (Input.touchCount != 1 ||
(touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
{
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(firstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
// Choose the Andy model for the Trackable that got hit.
GameObject prefab;
prefab = pointPrefab;
// Instantiate Andy model at the hit pose.
var pointObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
// Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
//andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
// world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make Andy model a child of the anchor.
pointObject.transform.parent = anchor.transform;
pointArray.Add(pointObject);
anchorCount++;
anchorcount.text = "Points: " + anchorCount;
}
}
}
private void _UpdateApplicationLifecycle()
{
// Exit the app when the 'back' button is pressed.
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
// Only allow the screen to sleep when not tracking.
if (Session.Status != SessionStatus.Tracking)
{
const int lostTrackingSleepTimeout = 15;
Screen.sleepTimeout = lostTrackingSleepTimeout;
}
else
{
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
if (m_IsQuitting)
{
return;
}
QuitOnConnectionErrors();
}
private void _ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,
message, 0);
toastObject.Call("show");
}));
}
}
void QuitOnConnectionErrors()
{
// Quit if ARCore was unable to connect and give Unity some time for the toast to appear.
if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
_ShowAndroidToastMessage("Camera permission is needed to run this application.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
_ShowAndroidToastMessage("ARCore encountered a problem connecting. Please start the app again.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
}
}
The issue with the above code was resolved by setting the parent of the pointObject variable in the Instantiate object. The plane then showed up relative to the parent object.

How can i make the Invisible Walls script to work and take effect?

The idea is to make that when the player is walking to the edge of the terrain he will stop wont be able to continue and fall.
And in my case i want the objects that move forward when they collide with the invisible wall the object will turn lerp back and move to the other side of the invisible walls.
Another problem that might come up later i read about is that if the objects moving too fast to the invisible walls there is a bug that let them move through ? Not sure about it.
This is a screenshot showing the invisible walls. I created a box collider set the Is Trigger to be on and set the 500 600 500 same as the terrain size.
This is the script of the Invisible Walls: The script i attached it to the Terrain:
using UnityEngine;
using System.Collections;
public class InvisibleWalls : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerExit(Collider other)
{
}
}
This is the script that create the space ships clone of them and make them move forward. But when they get to the edge of the terrain they just gone out. And i want them to lkerp/turn back to the other side.
This script is attached to the Spheres GameObject:
using System;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Collections;
using System.Collections.Generic;
public class SphereBuilder : MonoBehaviour
{
public GameObject SpaceShip;
GameObject[] spheres;
public float moveSpeed = 50;
// for tracking properties change
private Vector3 _extents;
private int _sphereCount;
private float _sphereSize;
/// <summary>
/// How far to place spheres randomly.
/// </summary>
public Vector3 Extents;
/// <summary>
/// How many spheres wanted.
/// </summary>
public int SphereCount;
public float SphereSize;
private void Start()
{
spheres = GameObject.FindGameObjectsWithTag("MySphere");
}
private void OnValidate()
{
// prevent wrong values to be entered
Extents = new Vector3(Mathf.Max(0.0f, Extents.x), Mathf.Max(0.0f, Extents.y), Mathf.Max(0.0f, Extents.z));
SphereCount = Mathf.Max(0, SphereCount);
SphereSize = Mathf.Max(0.0f, SphereSize);
}
private void Reset()
{
Extents = new Vector3(250.0f, 20.0f, 250.0f);
SphereCount = 100;
SphereSize = 20.0f;
}
private void Update()
{
UpdateSpheres();
MoveShips ();
}
private void MoveShips()
{
foreach (Transform child in spheres[0].transform)
{
child.transform.position += Vector3.forward * Time.deltaTime * moveSpeed;
}
}
private void UpdateSpheres()
{
if (Extents == _extents && SphereCount == _sphereCount && Mathf.Approximately(SphereSize, _sphereSize))
return;
// cleanup
var spheres = GameObject.FindGameObjectsWithTag("Sphere");
foreach (var t in spheres)
{
if (Application.isEditor)
{
DestroyImmediate(t);
}
else
{
Destroy(t);
}
}
var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
throw new InvalidOperationException("Terrain not found");
for (var i = 0; i < SphereCount; i++)
{
var o = Instantiate(SpaceShip);
o.tag = "Sphere";
o.transform.SetParent(gameObject.transform);
o.transform.localScale = new Vector3(SphereSize, SphereSize, SphereSize);
// get random position
var x = Random.Range(-Extents.x, Extents.x);
var y = Extents.y; // sphere altitude relative to terrain below
var z = Random.Range(-Extents.z, Extents.z);
// now send a ray down terrain to adjust Y according terrain below
var height = 10000.0f; // should be higher than highest terrain altitude
var origin = new Vector3(x, height, z);
var ray = new Ray(origin, Vector3.down);
RaycastHit hit;
var maxDistance = 20000.0f;
var nameToLayer = LayerMask.NameToLayer("Terrain");
var layerMask = 1 << nameToLayer;
if (Physics.Raycast(ray, out hit, maxDistance, layerMask))
{
var distance = hit.distance;
y = height - distance + y; // adjust
}
else
{
Debug.LogWarning("Terrain not hit, using default height !");
}
// place !
o.transform.position = new Vector3(x, y, z);
}
_extents = Extents;
_sphereCount = SphereCount;
_sphereSize = SphereSize;
}
}
And this is a small short video clip showing what happen to the space ships when they get to the terrain edge:
Spaceships video clip
Update what i did so far:
In top of script added:
public Terrain terrain;
private Vector3 boundLower;
private Vector3 boundUpper;
In Start function i added:
private void Start()
{
spheres = GameObject.FindGameObjectsWithTag("MySphere");
var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
throw new InvalidOperationException("Terrain not found");
boundLower = terrain.transform.position - terrain.transform.size / 2;
boundUpper = terrain.transform.position + terrain.transform.size / 2;
}
But getting errors on both lines: size property not exist:
boundLower = terrain.transform.position - terrain.transform.size / 2;
boundUpper = terrain.transform.position + terrain.transform.size / 2;
And changed the MoveShips function to this:
private Vector3 direction = Vector3.forward;
private void MoveShips() {
foreach (var child in spheres) {
var pos = child.transform.position + direction * Time.deltaTime * moveSpeed;
pos.x = Mathf.Clamp(pos.x, boundLower.x, boundUpper.x);
pos.z = Mathf.Clamp(pos.z, boundLower.z, boundUpper.z);
if (pos.x == boundLower.x || pos.x == boundUpper.x) direction.x = - direction.x;
if (pos.z == boundLower.z || pos.z == boundUpper.z) direction.z = - direction.z;
child.transform.position = pos;
}
}
I would suggest modifying MoveShips() changing Vector3.forward to a variable and flipping it when bounds are reached:
private Vector3 direction = Vector3.forward;
private void MoveShips() {
foreach (var child in spheres) {
var pos = child.transform.position + direction * Time.deltaTime * moveSpeed;
pos.x = Mathf.Clamp(pos.x, boundLower.x, boundUpper.x);
pos.z = Mathf.Clamp(pos.z, boundLower.z, boundUpper.z);
if (pos.x == boundLower.x || pos.x == boundUpper.x) direction.x = - direction.x;
if (pos.z == boundLower.z || pos.z == boundUpper.z) direction.z = - direction.z;
child.transform.position = pos;
}
}
This will remove unnecessary dependence on object collision engine for such a simple thing. Note, how this is making all ships to change direction when furthest reaches the bound. If you want them to move separately, you will need to move this logic to a separate script and attach it to a ship prefab.
And the bounds (boundLower and boundUpper) can be set either as script variables in editor or calculated from terrain, like:
boundLower = terrain.transform.position - terrain.TerrainData.size / 2;
boundUpper = terrain.transform.position + terrain.TerrainData.size / 2;
I would also suggest to move this:
var withTag = GameObject.FindWithTag("Terrain");
if (withTag == null)
throw new InvalidOperationException("Terrain not found");
out of Update() into Start() unless you do something really funky with it in the process.
Lets start working though your problems one by one :
Question : The objects do not collide, why?
Answer : Objects do not collide from with-in the collider, only from the outside.
What you need in your case is 4 box collider, one at each edge of the map
Question : Another problem that might come up later i read about is that if the objects moving too fast to the invisible walls there is a bug that let them move through ? Not sure about it.
This is only a problem with objects moving at bullet-like speeds, you could edit the rigidbody to have detection mode : "continuous" or continuous-dynamic which will avoid this issue
The scripts, i do not think you would need them in this case, your original idea was good, just the implementation with a single collider over the whole terrain, instead of 4 seperate "wall" colliders, was the issue. As for the rest of the logic, i did not try decipher through that, thus i can not comment on it.

How to have only one tile selected at a time in a hex grid in Unity

as the title says! I'm working on a sort of Civilization type city builder game as practice for the coming school year (only a second year video game programming student!).
I've already gotten a grid generated in game, which looks like:
This!
As you can see I've already gotten a rudimentary selection system set up, wherein currently I can only select one tile at a time until I deselect it, then I can select a new tile. The tiles are selected using an OnClick function tied to a collider on the prefab. (will include my code I have currently at the end!)
What I'm wondering how to do is have a tile deselect automatically whenever I select a new tile, so I have only one tile selected at a time.
This is what I have for now for selection.
public void OnMouseDown() {
if (GameManager.Instance.tileSelected == false) {
if (enabled == false) {
tileOutlineSprite.SetActive (true);
enabled = true;
GameManager.Instance.tileSelected = true;
this.tileInfo.text = tileType;
}
}
else if (enabled == true) {
tileOutlineSprite.SetActive (false);
enabled = false;
GameManager.Instance.tileSelected = false;
this.tileInfo.text = " ";
}
}
And this is what I'm currently using to generate my grid! I know it might be a lil messy for now, I'm planning on cleaning it up and refining it as I go on!
void generateMap() {
map = new List<List<TileSelect>>(); //generatign the playing field, making a grid of tile prefabs, and storing their positiosn in a 2d list
for (int i = 0; i < mapSizeX; i++) {
List <TileSelect> row = new List<TileSelect>();
for (int j = 0; j < mapSizeY; j++) {
if (i == 0) {
iDiff = 0.8f;
}
if (j % 2 == 0) {
iDiff = i + (.2f * (i+1));
} else if (i != 0) {
iDiff = i + 0.6f + (.2f * (i+1));
}
jDiff = j + (.04f * j);
int rand = Random.Range (1, 101);
if (rand <= 45) {
TileSelect tile = ((GameObject)Instantiate (HeavyForestTile, new Vector3 (iDiff, jDiff, 0), Quaternion.Euler (new Vector3 ()))).GetComponent<TileSelect> ();
tile.gridPosition = new Vector2 (i, j);
tile.tileType = "Heavy Forest";
tile.GetComponent<TileSelect> ().tileInfo = GameObject.Find ("InfoText").GetComponent<Text>();
row.Add (tile);
} else if (rand >= 45 && rand <= 70) {
TileSelect tile = ((GameObject)Instantiate (LightForestTile, new Vector3 (iDiff, jDiff, 0), Quaternion.Euler (new Vector3 ()))).GetComponent<TileSelect> ();
tile.gridPosition = new Vector2 (i, j);
tile.tileType = "Light Forest";
tile.GetComponent<TileSelect> ().tileInfo = GameObject.Find ("InfoText").GetComponent<Text>();
row.Add (tile);
} else if (rand >= 70 && rand <= 90 ) {
TileSelect tile = ((GameObject)Instantiate (GrassTile, new Vector3 (iDiff, jDiff, 0), Quaternion.Euler (new Vector3 ()))).GetComponent<TileSelect> ();
tile.gridPosition = new Vector2 (i, j);
tile.tileType = "Grassland";
tile.GetComponent<TileSelect> ().tileInfo = GameObject.Find ("InfoText").GetComponent<Text>();
row.Add (tile);
} else if (rand >= 90 && rand <= 97) {
TileSelect tile = ((GameObject)Instantiate (GrassRockTile, new Vector3 (iDiff, jDiff, 0), Quaternion.Euler (new Vector3 ()))).GetComponent<TileSelect> ();
tile.gridPosition = new Vector2 (i, j);
tile.tileType = "Light Rocks";
tile.GetComponent<TileSelect> ().tileInfo = GameObject.Find ("InfoText").GetComponent<Text>();
row.Add (tile);
} else if (rand >= 97 && rand <= 100) {
TileSelect tile = ((GameObject)Instantiate (GrassRock2Tile, new Vector3 (iDiff, jDiff, 0), Quaternion.Euler (new Vector3 ()))).GetComponent<TileSelect> ();
tile.gridPosition = new Vector2 (i, j);
tile.tileType = "Heavy Rocks";
tile.GetComponent<TileSelect> ().tileInfo = GameObject.Find ("InfoText").GetComponent<Text>();
row.Add (tile);
}
}
map.Add(row);
}
Oh! and the game is in 2d if that matters for a solution! Let me know if you need anymore info, I'll happily supply it!
A simple way would be to add an additional member to your game manager class:
public class GameManager
{
TileSelect _selectedTile;
public TileSelect selectedTile
{
get { return _selectedTile; }
set
{
//unhighlight the previous selected tile
_selectedTile = value;
//highlight the newly selected tile
}
}
...
}
Include a setter such that everytime you change the selected tile, it unhighlights the selected tile and highlights the new selected tile.
Simply change the selected tile when it is clicked:
void onClick(...)
{
...
//on raycast hit with the 2d tile (targetTile)
gameManager.selectedTile = targetTile;
}

how can create touch screen android scroll in unity3d?

I want to create an Android game with Unity3d. This game has an upgrade list with a touchable scroll. I use this code to create that but when I move finger in touch screen, scroll move hard and with a jump, I want it to move softly and like Android effects.
scrollPosition1 = GUI.BeginScrollView(Rect (0,400,Screen.width,175),
scrollPosition1, Rect (0, 0, 650, 0));
// touch screen
if(Input.touchCount==1 &&
Screen.height -Input.GetTouch(0).position.y > 450 - scrollPositionHome.y &&
Screen.height - Input.GetTouch(0).position.y < 600 - scrollPositionHome.y)
{
var touchDelta2 : Vector2 = Input.GetTouch(0).deltaPosition;
scrollPosition1.x +=touchDelta2.x;
}
for (i=0;i < ImgSliderProducts.Length;i++)
{
GUI.DrawTexture(Rect(20+(i* 100),10,100,100),
ImgSliderProducts[i],ScaleMode.ScaleToFit,true);
}
GUI.EndScrollView();
using UnityEngine;
using System.Collections;
public class scrollView : MonoBehaviour {
Vector2 scrollPosition;
Touch touch;
// The string to display inside the scrollview. 2 buttons below add & clear this string.
string longString = "This is a long-ish string";
void OnGUI () {
scrollPosition = GUI.BeginScrollView(new Rect(110,50,130,150),scrollPosition, new Rect(110,50,130,560),GUIStyle.none,GUIStyle.none);
for(int i = 0;i < 20; i++)
{
GUI.Box(new Rect(110,50+i*28,100,25),"xxxx_"+i);
}
GUI.EndScrollView ();
}
void Update()
{
if(Input.touchCount > 0)
{
touch = Input.touches[0];
if (touch.phase == TouchPhase.Moved)
{
scrollPosition.y += touch.deltaPosition.y;
}
}
}
}

Categories

Resources