Presently trying to work on a script that allows a ball to take cosmetic mesh damage as it goes through a level. Problem is, Ive been having trouble finding the proper equation for moving the vertexs.
Heres what I have thusfar
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
public class MeshDenter : MonoBehaviour {
Vector3[] originalMesh;
public float dentFactor;
public LayerMask collisionMask;
private MeshFilter meshFilter;
void Start() {
meshFilter = GetComponent<MeshFilter>();
originalMesh = meshFilter.mesh.vertices;
}
void OnCollisionEnter(Collision collision) {
Vector3[] meshCoordinates = originalMesh;
// Loop through collision points
foreach (ContactPoint point in collision.contacts) {
// Index with the closest distance to point.
int lastIndex = 0;
// Loop through mesh coordinates
for (int i = 0; i < meshCoordinates.Length; i++) {
// Check to see if there is a closer index
if (Vector3.Distance(point.point, meshCoordinates[i])
< Vector3.Distance(point.point, meshCoordinates[lastIndex])) {
// Set the new index
lastIndex = i;
}
}
// Move the vertex
meshCoordinates[lastIndex] += /*Insert Rest Of Equation Here*/;
}
meshFilter.mesh.vertices = meshCoordinates;
}
void Reset() {
meshFilter.mesh.vertices = originalMesh;
}
}
Quoted from:
http://answers.unity3d.com/questions/962794/mesh-collision-damage.html#answer-966389
I would suggest two options:
Use a random deformation like:
meshCoordinates[lastIndex] += new Vector3(Random.Range(-DeformScale,DeformScale),
Random.Range(-DeformScale,DeformScale),
Random.Range(-DeformScale,DeformScale));
Dent inwards by offsetting the vertex by the inverse normal like:
meshCoordinates[lastIndex] -= meshCoordinates[lastIndex].normalized * DeformScale;
Related
i am new here. I was studing procedural terrain with meshes. And i started a make a procedural terrain like Minecraft. And i don't know how i can remove the hidden vertices and triangles in the hidden blocks.
The hidden vertices and triangles
My code:
Voxel.cs:
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshCollider))]
[RequireComponent(typeof(MeshRenderer))]
public class Voxel : MonoBehaviour {
public Vector3[] vertices;
public int[] triangles;
public Vector3 pos;
public GameObject chunk;
Mesh mesh;
public bool blockSolid;
public Voxel(Vector3 position, GameObject obj)
{
pos = position;
chunk = obj;
}
void Start ()
{
mesh = new Mesh();
//Cube(0,0,0);
}
public void Cube(int x, int y, int z)
{
GameObject cube = new GameObject("Cubo");
cube.AddComponent(typeof(MeshFilter));
cube.AddComponent(typeof(MeshCollider));
cube.AddComponent(typeof(MeshRenderer));
cube.transform.parent = chunk.transform;
mesh = cube.GetComponent<MeshFilter>().mesh;
//cube.transform.position = pos;
vertices = new Vector3[]
{
new Vector3(x,y,z), // 0
new Vector3(x,y+1,z), // 1
new Vector3(x+1,y+1,z), // 2
new Vector3(x+1,y,z), // 3
new Vector3(x+1,y,z+1), // 4
new Vector3(x+1,y+1,z+1), // 5
new Vector3(x,y+1,z+1), // 6
new Vector3(x,y,z+1) // 7
};
triangles = new int[]
{
0,1,2, 0,2,3, // Face frontal
3,2,5, 3,5,4, // Face direita
0,7,6, 0,6,1, // Face esquerda
7,4,5, 7,5,6, // Face traseira
1,6,5, 1,5,2, // Face superior
0,3,4, 0,4,7 // Face inferior
};
UpdateMesh();
}
void UpdateMesh()
{
mesh.Clear();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
}
}
Chunk.cs:
using System.Collections.Generic;
using UnityEngine;
public class Chunk : MonoBehaviour {
public int tx, ty, tz;
public Vector3 pos;
IEnumerator BuildChunk()
{
for (int x = 0; x < tx; x++)
{
for (int y = 0; y < ty; y++)
{
for (int z = 0; z < tz; z++)
{
pos = new Vector3(x,y,z);
Voxel block = new Voxel(pos, this.gameObject);
block.Cube(x,y,z);
yield return null;
}
}
}
}
void Start ()
{
StartCoroutine(BuildChunk());
}
}
I just need to remove the hidden vertices and triangles, but i don't know how i gonna make this.
The trick is to generate only the triangles that are visible to the player. So you shouldn't be generating cubes for every voxel, but a subset of the faces of a cube.
The way you go about this, is to check all 6 sides of each voxel. If a given side borders another voxel, then ignore that side and move on. If there is no voxel bordering the side, then add the corresponding cube face to that side. This will result in a monolithic mesh encompassing your entire terrain, or the terrain you loaded in.
I have a script that rotates some cubes around to mimic a slot machine. I updated the transforms size from 45 px per size to 40. The script is still behaving as if they were 45 by 45. I can't imagine why this is happening.
All transforms are 40 px in the inspector.
The transforms are moving by 45 pix as their speed. I don't know why.
I tried Space.Self, same thing.
The transforms even space themselves out to their old locations when the resetting function is called.
Any ideas?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Reel : MonoBehaviour
{
//This Variable Will Be Changed By The "Slots" Class To Control When The Reel Spins
public bool spin;
//Speed That Reel Will Spin
float speed;
public int updates = 0;
// Use this for initialization
void Start()
{
spin = false;
speed = 0.2f;
}
// Update is called once per frame
void Update()
{
if (spin)
{
foreach (Transform image in transform)//This Targets All Children Objects Of The Main Parent Object fghjfgh smooth Time.smoothDeltaTime *
{
//Direction And Speed Of Movement
image.transform.Translate(Vector2.right * speed, Space.World);
//Once The Image Moves Below A Certain Point, Reset Its Position To The Top
if (image.transform.position.x >= +3) { image.transform.position = new Vector2(image.transform.position.x -6, image.transform.position.y); }
}
updates = updates + 1;
}
}
//Once The Reel Finishes Spinning The Images Will Be Placed In A Random Position
public void RandomPosition()
{
List<int> parts = new List<int>();
//Add All Of The Values For The Original Y Postions
parts.Add(2);
parts.Add(1);
parts.Add(0);
parts.Add(-1);
parts.Add(-2);
parts.Add(-3);
foreach (Transform image in transform)
{
int rand = Random.Range(0, parts.Count);
//The "transform.parent.GetComponent<RectTransform>().transform.position.y" Allows It To Adjust To The Canvas Y Position)
image.transform.position = new Vector2(parts[rand] + transform.parent.GetComponent<RectTransform>().transform.position.x, image.transform.position.y);
parts.RemoveAt(rand);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Slots : MonoBehaviour
{
public Reel[] reel;
bool startSpin;
// Use this for initialization
void Start()
{
startSpin = false;
}
// Update is called once per frame
void Update()
{
if (!startSpin)//Prevents Interference If The Reels Are Still Spinning
{
if (Input.GetKeyDown(KeyCode.K))//The Input That Starts The Slot Machine
{
startSpin = true;
StartCoroutine(Spinning());
}
if (Input.GetKeyDown(KeyCode.H))//The Input That Starts The Slot Machine
{
reel[0].RandomPosition();
}
}
}
IEnumerator Spinning()
{
foreach (Reel spinner in reel)
{
//Tells Each Reel To Start Spnning
spinner.spin = true;
}
for (int i = 0; i < reel.Length; i++)
{
//Allow The Reels To Spin For A Random Amout Of Time Then Stop Them
//yield return new WaitForSeconds(Random.Range(1, 3));
while (reel[0].updates != 100)
{
yield return null;
}
reel[0].spin = false;
reel[0].updates = 0;
}
//Allows The Machine To Be Started Again
startSpin = false;
}
}
I'm making the board game known as Hex. When I click on a tile, it changes to either blue or yellow, but I need to also be able to know what the coordinates of that tile are.
I can't use...
rend.transform.position;
...because the the coordinates I want to receive look similar to this (0,0) being the bottom left and (0,1) above it:
The coordinates in the console are the one's I need to receive.
I printed those out by using the column and row variables when I generated the hex map:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HexMap : MonoBehaviour
{
// Use this for initialization
void Start()
{
GenerateMap();
}
public GameObject HexPrefab;
public void GenerateMap()
{
for (int column = 0; column < 11; column++)
{
for (int row = 0; row < 11; row++)
{
// Instantiate a Hex
Hex h = new Hex(column, row);
Instantiate(HexPrefab, h.Position(), Quaternion.identity, this.transform);
Debug.Log(column + "," + row);
}
}
}
}
I want to be able to get the coordinates when I click a hex tile using this script here:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
using UnityEngine.Networking;
public class ColorChange : MonoBehaviour {
public Color[]colors; // allows input of material colors in a set sized array
public SpriteRenderer rend; // what are we rendering? the hex
public enum Player {ONE, TWO};
public static Player currentPlayer = Player.ONE;
// Use this for initialization
void Start () {
rend = GetComponent<SpriteRenderer> (); // gives functionality for the renderer
}
void NextPlayer() {
if( currentPlayer == Player.ONE ) {
currentPlayer = Player.TWO;
}
else if( currentPlayer == Player.TWO) {
currentPlayer = Player.ONE;
}
}
// Update is called once per frame
void OnMouseDown () {
// if there are no colors present nothing happens
if (colors.Length == 0)
return;
if (currentPlayer == Player.ONE)
rend.color = colors [0];
else if (currentPlayer == Player.TWO)
rend.color = colors [1];
NextPlayer();
}
Here is the script I use to determine where the hex tiles need to be:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hex{
public Hex (int q, int r){
this.Q = q;
this.R = r;
}
public readonly int Q; // x
public readonly int R; // y
static readonly float WIDTH_MULTIPLIER = Mathf.Sqrt(3) / 2;
public Vector2 Position(){
float radius = 0.513f;
float height = radius * 2;
float width = WIDTH_MULTIPLIER * height;
float vert = height * 0.75f;
float horiz = width;
return new Vector2(horiz * (this.Q - this.R/2f), vert * this.R);
}
}
I was thinking I need to be able to assign each Hex Model the value of column and row when it is instantiated, but I'm not sure how to do that. I tried several solutions I found online as well as using GetComponent, but I wasn't able to make them work.
If anyone has an idea on how this might be possible I would greatly appreciate it!
The reason why GetComponent is not working in your case is because the Coordinates script is on a child object of the hex prefab. You could access a component on a child object by calling GetComponentInChildren. It would look something like the following:
// Instantiate a Hex
Hex h = new Hex(column, row);
// Instantiate the prefab
GameObject instance = Instantiate(HexPrefab, h.Position(), Quaternion.identity, this.transform);
// Let's find the coorinates component on the hex prefab instance.
Coordinates coordinates = instance.GetComponentInChildren<Coordinates>();
// now you may assign the column and row values to it
// ...
There are many possible approaches to this problem. But just keep in mind where in the prefab hierarchy the components are and you will be fine.
I am making an endless runner style game in unity where the floor tiles spawn randomly and endlessly in front of the player as they run and delete themselves after a certain distance behind the player this is all working fine and as intended however the individual tiles spawn about half way inside each other and as much as I try to debug my code I can't seem to effect them. Ideally, I want the code to do exactly what it's doing, but the tiles spawn end to end rather than inside each other.
Any help would be greatly appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tile_Manager : MonoBehaviour
{
public GameObject[] tilePrefabs;
private Transform playerTransform;
private float spawnZ = 5.0f;
private float tileLength = 5.0f;
private float safeZone = 7.0f;
private int amtTilesOnScreen = 10;
private int lastPrefabIndex = 0;
private List<GameObject> activeTiles;
// Use this for initialization
void Start () {
activeTiles = new List<GameObject>();
playerTransform = GameObject.FindGameObjectWithTag ("Player").transform;
for (int i = 0; i < amtTilesOnScreen; i++)
{
if (i < 2)
SpawnTile(0);
else
SpawnTile();
}
}
// Update is called once per frame
void Update () {
if (playerTransform.position.z - safeZone > (spawnZ - amtTilesOnScreen * tileLength))
{
SpawnTile();
DeleteTile();
}
}
private void SpawnTile(int prefabIndex = -1)
{
GameObject go;
if (prefabIndex == -1)
go = Instantiate(tilePrefabs[RandomPrefabIndex()]) as GameObject;
else
go = Instantiate(tilePrefabs[prefabIndex]) as GameObject;
go.transform.SetParent(transform);
go.transform.position = Vector3.forward * spawnZ;
spawnZ += tileLength;
activeTiles.Add (go);
}
private void DeleteTile()
{
Destroy(activeTiles [0]);
activeTiles.RemoveAt (0);
}
private int RandomPrefabIndex()
{
if (tilePrefabs.Length <= 1)
return 0;
int randomIndex = lastPrefabIndex;
while (randomIndex == lastPrefabIndex)
{
randomIndex = Random.Range(0, tilePrefabs.Length);
}
lastPrefabIndex = randomIndex;
return randomIndex;
}
}
stacked tiles
You need to take the length of a tile into account. Try changing this
go.transform.position = Vector3.forward * spawnZ;
to this
go.transform.position = Vector3.forward * (spawnZ + tileLength / 2);
to add half the tile length to the spawn position.
Wouldn't you want
go.transform.Translate(Vector3.forward * spawnZ);
not position?
As you're spawning things relative to the world coordinate system.
https://docs.unity3d.com/ScriptReference/Transform.Translate.html
I'm using an Array to multiply a 3D object randomly in the space, so i'm getting a lot of nice objects floating randomly over the y, x and z axes.
This object has also an Audio Source with a sound attached to it, which means that after applying the random-array-positioning I get different objects with different Audio Sources as well.
The problem is that I'm also changing the scale of those objects, which it's working super well, but the size/scale/radius of the Audio Source it's not changing at all.
How can I change the scale of the objects and change the size/scale/radius of the Audio Source at the same time, to match both equally or proportionally in size?
I'm looking here but I Can't figured out.
https://docs.unity3d.com/ScriptReference/AudioSource.html
This is the code that I'm using for:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class multipleObjectsGrandes : MonoBehaviour {
public GameObject prefabGrandes;
public GameObject[] gos;
public int cantidad;
public float minScaleObj;
public float maxScaleObj;
void Awake()
{
gos = new GameObject[cantidad];
for(int i = 0; i < gos.Length; i++)
{
//Position
Vector3 position = new Vector3(Random.Range(-40.0f, 40.0f), Random.Range(-40.0f, 40.0f), Random.Range(-40.0f, 40.0f));
GameObject clone = (GameObject)Instantiate(prefabGrandes, position, Quaternion.identity);
//Scale
clone.transform.localScale = Vector3.one * Random.Range(minScaleObj, maxScaleObj);
//Rotation
clone.transform.rotation = Quaternion.Euler(Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f));
gos[i] = clone;
}
}
}
This is the code that i'm using to multiply objects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class multipleObjectsGrandes : MonoBehaviour
{
public GameObject prefabGrandes;
public GameObject[] cuerpos;
public int cantidad;
public float minScaleObj;
public float maxScaleObj;
public float escalaMax;
void Awake ()
{
cuerpos = new GameObject[cantidad];
for (int i = 0; i < cuerpos.Length; i++) {
//Position
Vector3 position = new Vector3 (Random.Range (-40.0f, 40.0f), Random.Range (-40.0f, 40.0f), Random.Range (-40.0f, 40.0f));
GameObject clone = (GameObject)Instantiate (prefabGrandes, position, Quaternion.identity);
//Scale
clone.transform.localScale = Vector3.one * Random.Range (minScaleObj, maxScaleObj);
//Rotation
clone.transform.rotation = Quaternion.Euler (Random.Range (0.0f, 360.0f), Random.Range (0.0f, 360.0f), Random.Range (0.0f, 360.0f));
escalaMax = clone.transform.localScale.x;
//Debug.Log(escalaMax);
}
}
}
Everything is ok here when I'm debugging "escalaMax" in the console.
The variable "escalaMax" is the one that i'm passing to the other script which is inside the object that I'm multiplying which has an audioSource attached to it. This is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent (typeof(AudioSource))]
public class AudioRandomPitch : MonoBehaviour
{
public float startingPitch = 1;
public float minPitchRandom = 0;
public float maxPitchRandom = 0;
AudioSource audio;
public float audioScale;
void Start ()
{
startingPitch = Random.Range (minPitchRandom, maxPitchRandom);
audio = GetComponent<AudioSource> ();
audio.pitch = startingPitch;
GameObject theMultiplicator = GameObject.Find ("Multiplicador_deCuerpos");
multipleObjectsGrandes multiplicatorScript = theMultiplicator.GetComponent<multipleObjectsGrandes> ();
multiplicatorScript.escalaMax = audioScale;
//this is not working
audio.maxDistance = audioScale;
Debug.Log(audioScale);
}
}
Here I'm first saving the value coming from the other script escalaMax inside the new variable audioScale.
The problem now is when I try to pass the audioScale value to the audio.maxDistance var.
I'm super close I know, but as you can see, i'm not a really good programmer and I'm probably doing something stupidly wrong... :/
Thanks for the help!