How to make a 15 sliding puzzle game? - unity3d

I have created a game that has 16 spheres in it and they are swapping on mouse click. But I want to have 15 spheres and one empty gameobject, so as to make them slide with the help of an empty gameobject.and i also want to shuffle the spheres when game starts each time. How is it possible?
I follow this tutorial
After that I tried to make it, but my cubes get overlapped on one another while changing their position on start.
var xtemp ;
var ytemp ;
var slot : Transform;
var cubesPosition : Vector3[] = new Vector3[16];
var cubeGameObjects: GameObject[] = new GameObject[16];
function Start ()
{
ChangePosition();
AssignPositions();
}
function ChangePosition()
{
for(var i=0;i<cubeGameObjects.length;i++)
{
cubeGameObjects[i].transform.position;
}
slot.transform.position = new Vector3(Random.Range (1,4),Random.Range (1,4),10);
}
function AssignPositions()
{
for (var i = 0; i < cubesPosition.length; ++i)
cubeGameObjects[i].transform.position = cubesPosition[i];
}
function OnMouseUp() {
if(Vector3.Distance(transform.position,slot.position)==1)
{
xtemp = transform.position.x;
ytemp = transform.position.y;
transform.position.x=slot.position.x;
transform.position.y=slot.position.y;
slot.position.x = xtemp;
slot.position.y = ytemp;
}

Related

Unity 2D - Change the sprite by script DOESN'T WORK

I have multiple images then push them into "Sprite[] sprites".
I create a gameobjectPrefab and add Rigidbody2d + Box Colider 2d + SpriteRenderer.
I want to Instantiate number of gameobjectPrefabs equal to the number of other sprites.
But it doesn't work, plz teach me the problem. The Sprites don't change:
public Sprite[] sprites;
public GameObject diamondPrefab;
void Start()
{
CreateDiamondsListSprites();
}
void CreateDiamondsListSprites()
{
for (int i = 0; i < sprites.Length; i++)
{
var go = diamondPrefab;
go.GetComponent<SpriteRenderer>().sprite = sprites[i];
listAllDiamondsFromSpritesList.Add(go);
// Here is sample : i add to list<gameOject> to use later
Instantiate(listAllDiamondsFromSpritesList[index],listLocationPoint[index]);
}
}
Set the sprite on the instantiated gameObject, after instantiation
void CreateDiamondsListSprites()
{
for (int i = 0; i < sprites.Length; i++)
{
var go = Instantiate(diamondPrefab,listLocationPoint[index]);
go.GetComponent<SpriteRenderer>().sprite = sprites[i];
listAllDiamondsFromSpritesList.Add(go);
}
}

Unity - How to set the color of an individual face when clicking a mesh?

Yesterday others on Stack Overflow helped me determine how to recolor a mesh triangle to red by clicking on it, it works great, the only problem is that the 3 vertices that get recolored are shared between triangles. This results in coloration that looks rather smeared. I'm really hoping there's a way to color only a single face (or normal if you will).
I've attached the following script to my mesh that uses a raycast to determine the surface coordinate and translate a green cube there. The gif below will better illustrate this problem.
Once again, any help or insight into this would be greatly appreciated. Thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyRayDraw : MonoBehaviour
{
public GameObject cube;
private MeshRenderer meshRenderer;
Mesh mesh;
Vector3[] vertices;
Color[] colorArray;
private void Start()
{
mesh = transform.GetComponent<MeshFilter>().mesh;
vertices = mesh.vertices;
colorArray = new Color[vertices.Length];
for (int k = 0; k < vertices.Length; k++)
{
colorArray[k] = Color.white;
}
mesh.colors = colorArray;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Snap(hit.point); // Moves the green cube
int[] triangles = mesh.triangles;
var vertIndex1 = triangles[hit.triangleIndex * 3 + 0];
var vertIndex2 = triangles[hit.triangleIndex * 3 + 1];
var vertIndex3 = triangles[hit.triangleIndex * 3 + 2];
colorArray[vertIndex1] = Color.red;
colorArray[vertIndex2] = Color.red;
colorArray[vertIndex3] = Color.red;
mesh.colors = colorArray;
}
else
{
Debug.Log("no hit");
}
}
}
}
As you say the issue is that the vertices are shared between triangles but coloring is always vertex based.
The idea for a solution is:
for each vertex of the hit triangle check if it is used by other triangles
if so copy its position to create a new separated vertex
update the triangle to use the newly created vertex indices
(evtl.) use RecalculateNormals to make the triangles face outside without having to care about the order of provided vertices
using System.Linq;
using UnityEngine;
public class MyRayDraw : MonoBehaviour
{
public GameObject cube;
// Better to reference those already in the Inspector
[SerializeField] private MeshFilter meshFilter;
[SerializeField] private MeshRenderer meshRenderer;
[SerializeField] private MeshCollider meshCollider;
private Mesh _mesh;
private void Awake()
{
if (!meshFilter) meshFilter = GetComponent<MeshFilter>();
if (!meshRenderer) meshRenderer = GetComponent<MeshRenderer>();
if (!meshCollider) meshCollider = GetComponent<MeshCollider>();
_mesh = meshFilter.mesh;
// create new colors array where the colors will be created
var colors = new Color[_mesh.vertices.Length];
for (var k = 0; k < colors.Length; k++)
{
colors[k] = Color.white;
}
_mesh.colors = colors;
}
private void Update()
{
if (!Input.GetMouseButtonDown(0)) return;
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hit))
{
Debug.Log(hit.triangleIndex);
//cube.transform.position = hit.point;
// Get current vertices, triangles and colors
var vertices = _mesh.vertices;
var triangles = _mesh.triangles;
var colors = _mesh.colors;
// Get the vert indices for this triangle
var vert1Index = triangles[hit.triangleIndex * 3 + 0];
var vert2Index = triangles[hit.triangleIndex * 3 + 1];
var vert3Index = triangles[hit.triangleIndex * 3 + 2];
// Get the positions for the vertices
var vert1Pos = vertices[vert1Index];
var vert2Pos = vertices[vert2Index];
var vert3Pos = vertices[vert3Index];
// Now for all three vertices we first check if any other triangle if using it
// by simply count how often the indices are used in the triangles list
var vert1Occurrences = 0;
var vert2Occurrences = 0;
var vert3Occurrences = 0;
foreach (var index in triangles)
{
if (index == vert1Index) vert1Occurrences++;
else if (index == vert2Index) vert2Occurrences++;
else if (index == vert3Index) vert3Occurrences++;
}
// Create copied Lists so we can dynamically add entries
var newVertices = vertices.ToList();
var newColors = colors.ToList();
// Now if a vertex is shared we need to add a new individual vertex
// and also an according entry for the color array
// and update the vertex index
// otherwise we will simply use the vertex we already have
if (vert1Occurrences > 1)
{
newVertices.Add(vert1Pos);
newColors.Add(new Color());
vert1Index = newVertices.Count - 1;
}
if (vert2Occurrences > 1)
{
newVertices.Add(vert2Pos);
newColors.Add(new Color());
vert2Index = newVertices.Count - 1;
}
if (vert3Occurrences > 1)
{
newVertices.Add(vert3Pos);
newColors.Add(new Color());
vert3Index = newVertices.Count - 1;
}
// Update the indices of the hit triangle to use the (eventually) new
// vertices instead
triangles[hit.triangleIndex * 3 + 0] = vert1Index;
triangles[hit.triangleIndex * 3 + 1] = vert2Index;
triangles[hit.triangleIndex * 3 + 2] = vert3Index;
// color these vertices
newColors[vert1Index] = Color.red;
newColors[vert2Index] = Color.red;
newColors[vert3Index] = Color.red;
// write everything back
_mesh.vertices = newVertices.ToArray();
_mesh.triangles = triangles;
_mesh.colors = newColors.ToArray();
_mesh.RecalculateNormals();
}
else
{
Debug.Log("no hit");
}
}
}
Note, however, that this works with simple coloring but might not for complex textures with UV mapping. You would have to also update the mesh.uv if using UV mapped textures.

How to set second material to a second submesh in a combined mesh?

I have this code (not originally my invention) that is working fine, but I have hit upon a problem with it. I can't seem to render the second submesh, with another material.
I can't figure out the problem lies in [renderer] part or the 2nd "submesh" that is perhaps never combining.
#script RequireComponent(MeshFilter)
#script RequireComponent(MeshRenderer)
private var matarray : Material[] = new Material[2];
var mat : Material;
var mat2 : Material;
function Start () {
matarray[0] = mat;
matarray[1] = mat2;
for (var child in transform)
child.position += transform.position;
transform.position = Vector3.zero;
transform.rotation = Quaternion.identity;
var meshFilters = GetComponentsInChildren(MeshFilter);
var combine : CombineInstance[] = new CombineInstance[meshFilters.Length-1];
var index = 0;
for (var i = 0; i < meshFilters.Length; i++) {
if (meshFilters[i].sharedMesh == null)
continue;
combine[index].mesh = meshFilters[i].sharedMesh;
combine[index++].transform = meshFilters[i].transform.localToWorldMatrix;
renderer.sharedMaterials = matarray;
meshFilters[i].active = false;
}
GetComponent(MeshFilter).mesh = new Mesh();
GetComponent(MeshFilter).mesh.CombineMeshes(combine);
renderer.active = true;
//here seems to be the trouble.
renderer.sharedMaterials = matarray;
}
Alternatively I have tried,
renderer.sharedMaterials[1] = matarray[1];
In short, I'm in trouble. I have to save few draw calls, which is not looking good unless this gets fixed.

Unity game engine having camera follow script transform change depending on car selected script?

OVERALL GOAL: Have the camera change target to the selected car
I'm new to the unity game engine and got a bit of a problem.
So, I have a successful car selector which changes between cars and starts the match with that car. Everything there works. The only issue is that my "CarCameraScript" has a transform variable which is always 1 of the 3 cars. I want it to change dependant on the selected car.
Here is the look at the code of the CarCameraScript
#pragma strict
var car : Transform;
var distance: float = 6.4;
var height: float = 1.4;
var rotationDamping : float = 3.0;
var heightDamping: float = 2.0;
var zoomRatio : float = 0.5;
var DefaultFOV : float = 60;
private var rotationVector : Vector3;
function Start () {
}
function LateUpdate () {
var wantedAngel = rotationVector.y;
var wantedHeight = car.position.y + height;
var myAngel = transform.eulerAngles.y;
var myHeight = transform.position.y;
myAngel = Mathf.LerpAngle(myAngel,wantedAngel,rotationDamping*Time.deltaTime);
myHeight = Mathf.Lerp(myHeight,wantedHeight,heightDamping*Time.deltaTime);
var currentRotation = Quaternion.Euler(0,myAngel,0);
transform.position = car.position;
transform.position -= currentRotation*Vector3.forward*distance;
transform.position.y = myHeight;
transform.LookAt(car);
}
function FixedUpdate () {
var localVilocity = car.InverseTransformDirection(car.rigidbody.velocity);
if (localVilocity.z<-0.5) {
rotationVector.y = car.eulerAngles.y + 180;
} else {
rotationVector.y = car.eulerAngles.y;
}
var acc = car.rigidbody.velocity.magnitude;
camera.fieldOfView = DefaultFOV + acc*zoomRatio;
}
This is what it looks like on the side panel.
http://i.stack.imgur.com/lYJP7.jpg
The area that says none (transform) is the place that should be variable dependant on the currently selected car.
Now, Here is my other script being the CharacterSelectScript
#pragma strict
//this is the currently selected Player. Also the one that will be saved to PlayerPrefs
var selectedPlayer : int = 0;
function Update()
{
if (Input.GetMouseButtonUp (0)) {
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit, 100))
{
// The pink text is where you would put the name of the object you want to click on (has attached collider).
if(hit.collider.name == "Player1")
SelectedCharacter1(); //Sends this click down to a function called "SelectedCharacter1(). Which is where all of our stuff happens.
if(hit.collider.name == "Player2")
SelectedCharacter2();
if(hit.collider.name == "Player3")
SelectedCharacter3();
}
else
{
return;
}
}
}
function SelectedCharacter1() {
Debug.Log ("Character 1 SELECTED"); //Print out in the Unity console which character was selected.
selectedPlayer = 1;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
function SelectedCharacter2() {
Debug.Log ("Character 2 SELECTED");
selectedPlayer = 2;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
function SelectedCharacter3() {
Debug.Log ("Character 3 SELECTED");
selectedPlayer = 3;
PlayerPrefs.SetInt("selectedPlayer", (selectedPlayer));
}
How would I get it so that the SelectedPlayer changes the transform in the first script?
Any ideas?
I also have the prefab script which probably isnt important.
Also, should I join both scripts into one?
OVERALL GOAL: Have the camera change target to the selected car

Easeljs: Displayobject ontick event not work in for loop

i'm a newbie and i'm terrible at english but hopefully you can understand my problem
i create a simple space shooting game with easeljs, when i tried to create multiple bullets and assign an onTick handle to each one, i relize just one bullet fire out. Here is the code:
//handle fire(shooting)
if(fire && cd === 0){
for(var i=0; i<5; i++){
//codartjs.Bullet is a class extend createjs.Bitmap
var b = new codartjs.Bullet(bullet_img);
b.x = 200;
b.y = 200;
stage.addChild(b);
b.onTick = function(){
//this event handler work for only first instance
b.y -= 10;
};
}
cd = 100;
setTimeout(function(){
cd = 0;
},100);
}
What you can also try is having a central ticker and loop through each bullet element and update its position that way. Here is quick demo that will illustrate my point.
<script>
var canvas, stage;
var bullets;
var speed;
function init() {
stage = new createjs.Stage("test");
bullets = [];
var bg = new createjs.Shape();
bg.graphics.beginFill("#FFFFFF").drawRect(0, 0, stage.canvas.width, stage.canvas.height).endFill();
bg.cache(0, 0, stage.canvas.width, stage.canvas.height);
speed = 15;
stage.onClick = handleClick;
stage.mouseEnabled = true;
stage.enableMouseOver(10);
createjs.Ticker.setFPS(24);
stage.addChild(bg);
createjs.Ticker.addListener(window);
}
function getSprite() {
var s = new createjs.Shape();
s.graphics.beginFill("#000000").drawCircle(0, 0, 10).endFill();
return s;
}
function tick() {
for(var i=0;i<bullets.length;i++) {
var s = bullets[i];
s.x += speed;
}
stage.update();
}
function handleClick(event) {
var s = getSprite();
s.x = event.stageX;
s.y = event.stageY;
bullets.push(s);
stage.addChild(s);
}
</script>
Hope this helps.