How to Get Coordinates from Hex Map on Click in Unity - c#

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.

Related

SceneManager.LoadScene() is not working in the way i want

In my unity project i have 3 scenes.
Title
Play
Over
For achieving the flow Title -> Play -> Over. I had to start the game from Over scene. Over -> Title -> Play -> Over .. I don't want this. I want it to work when i start the game from Title scene. On doing so i am unable to change from Play -> Over.
for Title scene
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LoadSceneOnInput : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetAxis("Submit") == 1) {
SceneManager.LoadScene("Play");
}
}
}
for Over Scene
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameOverInput : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetAxis("Submit") == 1) {
SceneManager.LoadScene("Title");
}
}
}
Play's script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelGenerator : MonoBehaviour {
public GameObject floorPrefab;
public GameObject wallPrefab;
public GameObject ceilingPrefab;
public GameObject characterController;
public GameObject floorParent;
public GameObject wallsParent;
// allows us to see the maze generation from the scene view
public bool generateRoof = true;
// number of times we want to "dig" in our maze
public int tilesToRemove = 50;
public int mazeSize;
// spawns at the end of the maze generation
public GameObject pickup;
// this will determine whether we've placed the character controller
private bool characterPlaced = false;
// 2D array representing the map
private bool[,] mapData;
// we use these to dig through our maze and to spawn the pickup at the end
private int mazeX = 4, mazeY = 1;
// Use this for initialization
void Start () {
// initialize map 2D array
mapData = GenerateMazeData();
// create actual maze blocks from maze boolean data
for (int z = 0; z < mazeSize; z++) {
for (int x = 0; x < mazeSize; x++) {
if (mapData[z, x]) {
CreateChildPrefab(wallPrefab, wallsParent, x, 1, z);
CreateChildPrefab(wallPrefab, wallsParent, x, 2, z);
CreateChildPrefab(wallPrefab, wallsParent, x, 3, z);
} else if (!characterPlaced) {
// place the character controller on the first empty wall we generate
characterController.transform.SetPositionAndRotation(
new Vector3(x, 1, z), Quaternion.identity
);
// flag as placed so we never consider placing again
characterPlaced = true;
CreateChildPrefab(floorPrefab, floorParent, x, 0, z);
}
//create floor and ceiling
if(mapData[z, x]){
CreateChildPrefab(floorPrefab, floorParent, x, 0, z);
}else{
if((z > 0 && z < mazeSize - 1) && (x > 0 && x < mazeSize - 1)){
if(!(Random.value > 0.8)){
CreateChildPrefab(floorPrefab, floorParent, x, 0, z);
}
}
}
if (generateRoof) {
CreateChildPrefab(ceilingPrefab, wallsParent, x, 4, z);
}
}
}
// spawn the pickup at the end
var myPickup = Instantiate(pickup, new Vector3(mazeX, 1, mazeY), Quaternion.identity);
myPickup.transform.localScale = new Vector3(0.25f, 0.25f, 0.25f);
}
void Update() {
if(characterController.transform.position.y < -5){
SceneManager.LoadScene("Over");
}
}
// generates the booleans determining the maze, which will be used to construct the cubes
// actually making up the maze
bool[,] GenerateMazeData() {
bool[,] data = new bool[mazeSize, mazeSize];
// initialize all walls to true
for (int y = 0; y < mazeSize; y++) {
for (int x = 0; x < mazeSize; x++) {
data[y, x] = true;
}
}
// counter to ensure we consume a minimum number of tiles
int tilesConsumed = 0;
// iterate our random crawler, clearing out walls and straying from edges
while (tilesConsumed < tilesToRemove) {
// directions we will be moving along each axis; one must always be 0
// to avoid diagonal lines
int xDirection = 0, yDirection = 0;
if (Random.value < 0.5) {
xDirection = Random.value < 0.5 ? 1 : -1;
} else {
yDirection = Random.value < 0.5 ? 1 : -1;
}
// random number of spaces to move in this line
int numSpacesMove = (int)(Random.Range(1, mazeSize - 1));
// move the number of spaces we just calculated, clearing tiles along the way
for (int i = 0; i < numSpacesMove; i++) {
mazeX = Mathf.Clamp(mazeX + xDirection, 1, mazeSize - 2);
mazeY = Mathf.Clamp(mazeY + yDirection, 1, mazeSize - 2);
if (data[mazeY, mazeX]) {
data[mazeY, mazeX] = false;
tilesConsumed++;
}
}
}
return data;
}
// allow us to instantiate something and immediately make it the child of this game object's
// transform, so we can containerize everything. also allows us to avoid writing Quaternion.
// identity all over the place, since we never spawn anything with rotation
void CreateChildPrefab(GameObject prefab, GameObject parent, int x, int y, int z) {
var myPrefab = Instantiate(prefab, new Vector3(x, y, z), Quaternion.identity);
myPrefab.transform.parent = parent.transform;
}
}

Unity Tilemaps, Single Tile Collision detection for highlighting Tiles/Cells, strange behaviour

Ive been working for a few days on this problem, trying to create a square grid of tiles, using Unity Tilemaps seems to be the most efficient way, and it has a lot built in already.
I want to highlight the tiles around the player so that he will see what the legal moves are.
I use a second Tilemap for this, on top of the basemap(ground/grass).
The second Tilemap, the highlightsMap is made up of invisible Tiles, which will turn into highlighted Tiles when a Physics.SphereOverlap occurs, or a Physics2D.CircleAll
To detect every Tile, I have added a box collider on an empty object and I made a grid of these colliders on top of the Tilemap grid, so that:
Box Collider at Position (2,4,0) is exactly on top of Tile at Position(2,4,0)
This should be the most straightforward way to handle this, as you can change a Tile, using Tilemap.SetTile(Vector3Int Pos, Tile tile)
The problem is very strange however. The colliders have the correct positional values to be able to reference the tiles exactly underneath them, just through that position data. As explained above, and I have double checked this, the collider empties have the exact same position as the tiles underneath them, no conversion is needed.
The problem is that the tiles are not highlighting around the player as expected, instead a few next to the player are highlighted and others arent, the Physics.OverlapSphere I am using only works on 3D Colliders, which is why I added them as another grid on top of everything.
Using Physics2D.CircleAll, unfortunately does not detect any 2D colliders on the tiles themselves(Sprite, or Grid), not sure if that is intended to work like that anyway.
Collision Grid Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class scr_ColliderGrid : MonoBehaviour
{
public GameObject eCollider;
public Tile invisibleTile;
public Tile highlightTile;
public Tilemap highlightMap;
public int xSize, ySize;
private Vector3Int[] gridArray; // Tilemaps use Vector3Int BUT only use (X, Y, 0) !!!!!!!
private int xC = 0, yC = 0, i = 0;
private Tile[] tiles;
private Vector3Int previous;
private void Start()
{
gridArray = new Vector3Int[xSize * ySize];
tiles = new Tile[xSize * ySize];
GenerateCollisionGrid();
}
private void GenerateCollisionGrid()
{
for (xC = 0; xC < xSize; xC++)
{
for (yC = 0; yC < ySize; yC++)
{
Vector3Int newPos = new Vector3Int(xC, yC, 0); // 2, 4, 0
Vector3Int newColPos = new Vector3Int(xC, yC, 0); // 2, 4, 0 //This used to be different values, but now they are exactly the same.
if (invisibleTile != null)
{
Tile tile = Instantiate(invisibleTile, newPos, Quaternion.identity, transform);
tiles[i] = tile;
GameObject col = Instantiate(eCollider, newColPos, Quaternion.identity, transform);
}
gridArray[i] = newPos;
i++;
}
}
highlightMap.SetTiles(gridArray, tiles);
highlightMap.SetTile(new Vector3Int(2,4,0), highlightTile); // 2,4,0 //Test to see if positions are the same. (collider and tiles)
}
Player Highlight Legal Moves Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class scr_TankMoves : MonoBehaviour
{
public Tile highlightTile;
public TileBase[] highlightTiles;
public Tilemap highlightMap;
public int maxMoveTiles;
public bool highlight;
private Vector3Int previous, previousLeft, previousRight, previousForward, previousAft, previousVect;
private Vector3Int[] previousVectors;
void Start()
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
transform.localPosition = new Vector3(transform.localPosition.x,
transform.localPosition.y + 1,
transform.localPosition.z );
}
if (Input.GetKeyDown(KeyCode.S))
{
transform.localPosition = new Vector3(transform.localPosition.x,
transform.localPosition.y - 1,
transform.localPosition.z );
}
if (Input.GetKeyDown(KeyCode.D))
{
transform.localPosition = new Vector3(transform.localPosition.x + 1,
transform.localPosition.y,
transform.localPosition.z);
}
if (Input.GetKeyDown(KeyCode.A))
{
transform.localPosition = new Vector3(transform.localPosition.x - 1,
transform.localPosition.y,
transform.localPosition.z);
}
}
void LateUpdate()
{
if (highlight)
HighlightMoves();
else EraseHighlights();
}
private void HighlightMoves()
{
previousVectors = new Vector3Int[1];
highlightMap.SetTiles(previousVectors, null);
int tMax = 0;
Collider[] legalTiles = Physics.OverlapSphere(transform.position, maxMoveTiles/2);
previousVectors = new Vector3Int[legalTiles.Length];
foreach (Collider col in legalTiles)
{
//Vector3 conversionVector = new Vector3(col.transform.localPosition.x, col.transform.localPosition.y, col.transform.localPosition.z);
Vector3Int tileVector = Vector3Int.FloorToInt(col.transform.position);
previousVectors[tMax] = tileVector;
tMax++;
}
highlightMap.SetTiles(previousVectors, highlightTiles);
}
private void EraseHighlights()
{
//highlightMap.SetTile(previousForward, null);
//highlightMap.SetTile(previousAft, null);
//highlightMap.SetTile(previous, null);
//highlightMap.SetTile(previousRight, null);
//highlightMap.SetTile(previousLeft, null);
highlightMap.SetTiles(previousVectors, null);
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, maxMoveTiles/2);
}
}
}
If you open a new 3D Project in Unity and setup a grid with a Tilemap, called highlightMap in my code example, you should be able to recreate this exactly, using the 2 scripts.
Everything is oriented in 2D, this means x+ is Right y+ is forward and z+ is up/dephth (unused by tilemaps).
The empty Collider prefab I have is an empty GO with pos 0,0,0. it has another empty GO Child, which has the Box Collider Component, and the transform value of this child is 0.5,0.5,0.5, so that the Collider is centered on top of each tile.
This is after 0 moves, so just pressed Play:
This is after 1 move forward, (y+1):
Instead of going by colliders at all afaik you could also just use GridLayout.WorldToCell like e.g.
Tilemap yourTileMap;
// see https://docs.unity3d.com/ScriptReference/Tilemaps.Tilemap-layoutGrid.html
var grid = yourTileMap.layoutGrid;
// The "Grid" implements "GridLayout"
// see https://docs.unity3d.com/ScriptReference/Grid.html
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);
Then if you need to get multiple tiles I would probably go the "lazy/stupid" way and just do something like e.g.
var currentCellPos = grid.WorldToCell(transform.position);
var currentCell = yourTileMap.GetTile(currentCellPos);
var leftCellPos = grid.WorldToCell(transform.position - transform.right * someRange);
var leftCell = yourTileMap.GetTile(leftCellPos);
var rightCellPos = grid.WorldToCell(transform.position + transform.right * someRange);
var rightCell = yourTileMap.GetTile(rightCellPos);
var frontCellPos = grid.WorldToCell(transform.position + transform.forward * someRange);
var frontCell = yourTileMap.GetTile(frontCellPos);
var backCellPos = grid.WorldToCell(transform.position - transform.forward * someRange);
var backCell = yourTileMap.GetTile(backCellPos);
highlightTiles[tMax] = Instantiate(highlightTile, col.transform.parent.position, Quaternion.identity, transform);
I dont know why, but apparently I didnt instantiate the tiles themselves into an Array of tiles, so everytime I was ''placing'' them on the grid, it was actually placing an empty array.
Now its fixed! Just need to find a nice way to erase all after a move and im set!

Unable to access values from positions component on Line Renderer inUnity

Here I'm generating a line renderer with multiple points to produce a wave out of the points and now I need to access some points in that list to do further calculations on it.
The problem is the Vector 2 List that I'm using to add the points to does not show the same points as that of Positions parameter on the line renderer component as I'm also moving the parent component on which this line renderer component is attached and the position on the default line renderer component shows the positional values in World Space which is what I need to access, whereas the Vector 2 list that I've generated shows points in Local Space, where only one value appears to be changing.
How can I access the World space values without moving too much of my current architecture?
I need to access Z axis points on Positions elements on Line Renderer component for comparing the positional values and also get Index of the same points as well.
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(LineRenderer))]
public class tail : MonoBehaviour {
public GameObject tailComponent, diameterBall, playButton, statisticalToolSubLevel;
public float speed;
public float pointSpacing = .01f;
public List<Vector2> points;
LineRenderer line;
public Text maxima, minima, mean, median;
public TapToMeasure otherScript;
// Use this for initialization
void Start () {
line = GetComponent<LineRenderer>();
points = new List<Vector2>();
SetPoint();
}
// Update is called once per frame
void Update () {
if (!playButton.activeSelf)
{
if (Vector3.Distance(points.Last(), diameterBall.transform.position) > pointSpacing)
{
SetPoint();
}
}
/*
int result1 = 0;
result1 = BinarySearchRecursive(points.position.x, otherScript.statisticalMarkerList[0].transform.position.x, 0, points.Count);
*/
if (statisticalToolSubLevel.activeSelf)
{
for(int i=0; i<points.Count; i++)
{
if(Mathf.Approximately(points[i].x, otherScript.statisticalMarkerList[0].transform.position.x))
{
Debug.Log("Task acheieved");
//return i;
}
if (points[i].x < otherScript.statisticalMarkerList[0].transform.position.x)
{
i += 1;
//Debug.Log(i);
}
}
}
}
void SetPoint()
{
points.Add(diameterBall.transform.position);
line.positionCount = points.Count; //count<=100 or whatever number or edge of the room
//line.SetPosition(points.Count - 1, diameterBall.transform.position);
line.SetPosition(points.Count - 1, tailComponent.transform.InverseTransformPoint(diameterBall.transform.position));
}
public static int BinarySearchRecursive(float[] inputArray, float query, int min_idx, int max_idx)
{
if (min_idx > max_idx)
{
return -1;
}
else
{
int mid = (min_idx + max_idx) / 2;
if (query == inputArray[mid])
{
return mid;
}
else if (query < inputArray[mid])
{
return BinarySearchRecursive(inputArray, query, min_idx, mid);
}
else if (min_idx + 1 == max_idx)
{
return mid;
}
else
{
return BinarySearchRecursive(inputArray, query, mid, max_idx);
}
}
}
}
You can use transform.TransformVector(Vector3 point) to convert from the local space of your transform to worldspace.
Thanks to a friend I was able to solve this problem.
All I was needed to do was access those values in the line renderer position component by creating a new different Vector3 array and getting the positions in the SetPoint function.
Additional Code:
Vector3[] finalpositions;
void SetPoint()
{
points.Add(diameterBall.transform.InverseTransformPoint(diameterBall.transform.position));
line.positionCount = points.Count; //count<=100 or whatever number or edge of the room
//line.SetPosition(points.Count - 1, diameterBall.transform.position);
line.SetPosition(points.Count - 1, tailComponent.transform.InverseTransformPoint(diameterBall.transform.position));
finalpositions = new Vector3[points.Count];
line.GetPositions(finalpositions);
}

How can I change the scale of a 3D Object and the Audio Source's radius in a proportionally way in Unity 5 using C#?

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!

Mesh Filter Cosmetic Damage

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;

Categories