Unity3d 物理用网格对撞机
我正在创建一个平铺的世界,平铺是由游戏对象组成的。不过,我想在这个游戏对象中加入物理元素。如果我为每个磁贴实例化一个游戏对象,我会得到一个帧降,如果我使用一个参考,每个磁贴的物理特性都是相同的(例如,一个球落在一个磁贴上,再往前走一点,它已经落在下一个磁贴上) 上述问题有解决办法吗 编辑:参见我添加的最后一部分 脚本:Unity3d 物理用网格对撞机,unity3d,Unity3d,我正在创建一个平铺的世界,平铺是由游戏对象组成的。不过,我想在这个游戏对象中加入物理元素。如果我为每个磁贴实例化一个游戏对象,我会得到一个帧降,如果我使用一个参考,每个磁贴的物理特性都是相同的(例如,一个球落在一个磁贴上,再往前走一点,它已经落在下一个磁贴上) 上述问题有解决办法吗 编辑:参见我添加的最后一部分 脚本: using UnityEngine; using System.Collections; using System; using System.Collections.Gener
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
/// <summary>
/// A double key dictionary.
/// </summary>
/// <typeparam name="K">
/// The first key type.
/// </typeparam>
/// <typeparam name="T">
/// The second key type.
/// </typeparam>
/// <typeparam name="V">
/// The value type.
/// </typeparam>
/// <remarks>
/// See http://noocyte.wordpress.com/2008/02/18/double-key-dictionary/
/// A Remove method was added.
/// </remarks>
public class DoubleKeyDictionary<K, T, V> : IEnumerable<DoubleKeyPairValue<K, T, V>>,
IEquatable<DoubleKeyDictionary<K, T, V>>
{
#region Constants and Fields
/// <summary>
/// The m_inner dictionary.
/// </summary>
private Dictionary<T, V> m_innerDictionary;
#endregion
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="DoubleKeyDictionary{K,T,V}"/> class.
/// Initializes a new instance of the <see cref="DoubleKeyDictionary<K, T, V>"/> class.
/// </summary>
public DoubleKeyDictionary()
{
this.OuterDictionary = new Dictionary<K, Dictionary<T, V>>();
}
#endregion
#region Properties
/// <summary>
/// Gets or sets OuterDictionary.
/// </summary>
private Dictionary<K, Dictionary<T, V>> OuterDictionary { get; set; }
#endregion
#region Public Indexers
/// <summary>
/// Gets or sets the value with the specified indices.
/// </summary>
/// <value></value>
public V this[K index1, T index2]
{
get
{
return this.OuterDictionary[index1][index2];
}
set
{
this.Add(index1, index2, value);
}
}
#endregion
#region Public Methods
/// <summary>
/// Clears this dictionary.
/// </summary>
public void Clear()
{
OuterDictionary.Clear();
if (m_innerDictionary!=null)
m_innerDictionary.Clear();
}
/// <summary>
/// Adds the specified key.
/// </summary>
/// <param name="key1">
/// The key1.
/// </param>
/// <param name="key2">
/// The key2.
/// </param>
/// <param name="value">
/// The value.
/// </param>
public void Add(K key1, T key2, V value)
{
if (this.OuterDictionary.ContainsKey(key1))
{
if (this.m_innerDictionary.ContainsKey(key2))
{
this.OuterDictionary[key1][key2] = value;
}
else
{
this.m_innerDictionary = this.OuterDictionary[key1];
this.m_innerDictionary.Add(key2, value);
this.OuterDictionary[key1] = this.m_innerDictionary;
}
}
else
{
this.m_innerDictionary = new Dictionary<T, V>();
this.m_innerDictionary[key2] = value;
this.OuterDictionary.Add(key1, this.m_innerDictionary);
}
}
/// <summary>
/// Determines whether the specified dictionary contains the key.
/// </summary>
/// <param name="index1">
/// The index1.
/// </param>
/// <param name="index2">
/// The index2.
/// </param>
/// <returns>
/// <c>true</c> if the specified index1 contains key; otherwise, <c>false</c>.
/// </returns>
public bool ContainsKey(K index1, T index2)
{
if (!this.OuterDictionary.ContainsKey(index1))
{
return false;
}
if (!this.OuterDictionary[index1].ContainsKey(index2))
{
return false;
}
return true;
}
/// <summary>
/// Equalses the specified other.
/// </summary>
/// <param name="other">
/// The other.
/// </param>
/// <returns>
/// The equals.
/// </returns>
public bool Equals(DoubleKeyDictionary<K, T, V> other)
{
if (this.OuterDictionary.Keys.Count != other.OuterDictionary.Keys.Count)
{
return false;
}
bool isEqual = true;
foreach (var innerItems in this.OuterDictionary)
{
if (!other.OuterDictionary.ContainsKey(innerItems.Key))
{
isEqual = false;
}
if (!isEqual)
{
break;
}
// here we can be sure that the key is in both lists,
// but we need to check the contents of the inner dictionary
Dictionary<T, V> otherInnerDictionary = other.OuterDictionary[innerItems.Key];
foreach (var innerValue in innerItems.Value)
{
if (!otherInnerDictionary.ContainsValue(innerValue.Value))
{
isEqual = false;
}
if (!otherInnerDictionary.ContainsKey(innerValue.Key))
{
isEqual = false;
}
}
if (!isEqual)
{
break;
}
}
return isEqual;
}
/// <summary>
/// Gets the enumerator.
/// </summary>
/// <returns>
/// </returns>
public IEnumerator<DoubleKeyPairValue<K, T, V>> GetEnumerator()
{
foreach (var outer in this.OuterDictionary)
{
foreach (var inner in outer.Value)
{
yield return new DoubleKeyPairValue<K, T, V>(outer.Key, inner.Key, inner.Value);
}
}
}
/// <summary>
/// Removes the specified key.
/// </summary>
/// <param name="key1">
/// The key1.
/// </param>
/// <param name="key2">
/// The key2.
/// </param>
public void Remove(K key1, T key2)
{
this.OuterDictionary[key1].Remove(key2);
if (this.OuterDictionary[key1].Count == 0)
{
this.OuterDictionary.Remove(key1);
}
}
#endregion
#region Explicit Interface Methods
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}
/// <summary>
/// Represents two keys and a value.
/// </summary>
/// <typeparam name="K">
/// First key type.
/// </typeparam>
/// <typeparam name="T">
/// Second key type.
/// </typeparam>
/// <typeparam name="V">
/// Value type.
/// </typeparam>
public class DoubleKeyPairValue<K, T, V>
{
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="DoubleKeyPairValue{K,T,V}"/> class.
/// Initializes a new instance of the <see cref="DoubleKeyPairValue<K, T, V>"/> class.
/// </summary>
/// <param name="key1">
/// The key1.
/// </param>
/// <param name="key2">
/// The key2.
/// </param>
/// <param name="value">
/// The value.
/// </param>
public DoubleKeyPairValue(K key1, T key2, V value)
{
this.Key1 = key1;
this.Key2 = key2;
this.Value = value;
}
#endregion
#region Public Properties
/// <summary>
/// Gets or sets the key1.
/// </summary>
/// <value>The key1.</value>
public K Key1 { get; set; }
/// <summary>
/// Gets or sets the key2.
/// </summary>
/// <value>The key2.</value>
public T Key2 { get; set; }
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
public V Value { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Key1 + " - " + this.Key2 + " - " + this.Value;
}
#endregion
}
public class TerrainManager : MonoBehaviour {
public GameObject playerGameObject;
public GameObject referenceTerrain;
public int spread = 1;
public int rememberSpread = 3;
private int[] currentTerrainID;
private DoubleKeyDictionary<int, int, GameObject> terrainUsageData;
private Vector3 referencePosition;
private Vector2 referenceSize;
private Quaternion referenceRotation;
// Use this for initialization
void Start () {
currentTerrainID = new int[2];
terrainUsageData = new DoubleKeyDictionary<int, int, GameObject>();
referencePosition = referenceTerrain.transform.position;
referenceRotation = referenceTerrain.transform.rotation;
float width = 0;
float height = 0;
foreach(Renderer rend in referenceTerrain.GetComponentsInChildren<Renderer>()) {
if (rend.bounds.size.x > width)
width = rend.bounds.size.x;
if (rend.bounds.size.z > height)
height = rend.bounds.size.z;
}
referenceSize = new Vector2(width, height);
print (referenceSize);
}
// Update is called once per frame
void Update () {
Vector3 warpPosition = playerGameObject.transform.position;
TerrainIDFromPosition(ref currentTerrainID, ref warpPosition);
string dbgString = "";
dbgString = "CurrentID : " + currentTerrainID[0] + ", " + currentTerrainID[1] + "\n\n";
for(int i=-spread;i<=spread;i++)
{
for(int j=-spread;j<=spread;j++)
{
DropTerrainAt(currentTerrainID[0] + i, currentTerrainID[1] + j);
dbgString += (currentTerrainID[0] + i) + "," + (currentTerrainID[1] + j) + "\n";
}
}
Debug.Log(dbgString);
ReclaimTiles();
}
void TerrainIDFromPosition(ref int[] currentTerrainID, ref Vector3 position)
{
currentTerrainID[0] = Mathf.RoundToInt((position.x - referencePosition.x) / referenceSize.x);
currentTerrainID[1] = Mathf.RoundToInt((position.z - referencePosition.z) / referenceSize.y);
}
void DropTerrainAt(int i, int j)
{
if(terrainUsageData.ContainsKey(i,j))
{
// Restore the data for this tile
}
else
{
// Create a new data object
terrainUsageData[i,j] = CreateNewTerrainData();
}
ActivateUsedTile(i, j);
}
GameObject CreateNewTerrainData()
{
GameObject terr = (GameObject)Instantiate(referenceTerrain);
terr.SetActive(true);
return terr;
}
void ReclaimTiles()
{
foreach(DoubleKeyPairValue<int,int,GameObject> pair in terrainUsageData)
{
if (pair.Key1 > currentTerrainID[0] + rememberSpread || pair.Key1 < currentTerrainID[0] - rememberSpread ||
pair.Key2 > currentTerrainID[1] + rememberSpread || pair.Key2 < currentTerrainID[1] - rememberSpread) {
pair.Value.SetActive(false);
terrainUsageData.Remove(pair.Key1, pair.Key2);
}
}
}
void ActivateUsedTile(int i, int j)
{
terrainUsageData[i,j].transform.position =
new Vector3( referencePosition.x + i * referenceSize.x,
referencePosition.y,
referencePosition.z + j * referenceSize.y);
terrainUsageData[i,j].transform.rotation = referenceRotation;
terrainUsageData[i,j].SetActive(true);
foreach(Transform ct in terrainUsageData[i,j].transform) {
if (!ct.gameObject.name.Equals("Ground"))
ct.gameObject.rigidbody.isKinematic = false;
}
}
}
使用UnityEngine;
使用系统集合;
使用制度;
使用System.Collections.Generic;
///
///双键词典。
///
///
///第一个键类型。
///
///
///第二个键类型。
///
///
///值类型。
///
///
///看http://noocyte.wordpress.com/2008/02/18/double-key-dictionary/
///添加了删除方法。
///
公共类DoubleKeyDictionary:IEnumerable,
充足的
{
#区域常数和字段
///
///m_内部字典。
///
私家字典m_innerDictionary;
#端区
#区域构造函数和析构函数
///
///初始化类的新实例。
///初始化类的新实例。
///
公共DoubleKeyDictionary()
{
this.OuterDictionary=新字典();
}
#端区
#区域属性
///
///获取或设置OuterDictionary。
///
专用词典外部词典{get;set;}
#端区
#区域公共索引器
///
///获取或设置具有指定索引的值。
///
///
公共V本[K index1,T index2]
{
得到
{
返回这个.OuterDictionary[index1][index2];
}
设置
{
添加(index1,index2,value);
}
}
#端区
#区域公共方法
///
///清除此词典。
///
公共空间清除()
{
OuterDictionary.Clear();
如果(m_innerDictionary!=null)
m_innerDictionary.Clear();
}
///
///添加指定的键。
///
///
///钥匙1。
///
///
///钥匙2。
///
///
///价值。
///
公共无效添加(K键1、T键2、V值)
{
if(此.OuterDictionary.ContainsKey(键1))
{
if(此.m_innerDictionary.ContainsKey(键2))
{
this.OuterDictionary[key1][key2]=值;
}
其他的
{
this.m_innerDictionary=this.OuterDictionary[key1];
这个.m_innerDictionary.Add(键2,值);
this.OuterDictionary[key1]=this.m_innerDictionary;
}
}
其他的
{
this.m_innerDictionary=新字典();
这个.m_innerDictionary[key2]=值;
this.OuterDictionary.Add(键1,this.m_innerDictionary);
}
}
///
///确定指定的字典是否包含键。
///
///
///指数1。
///
///
///指数2。
///
///
///如果指定的index1包含键,则为true;否则为false。
///
公共bool ContainsKey(K index1,T index2)
{
如果(!this.OuterDictionary.ContainsKey(index1))
{
返回false;
}
if(!this.OuterDictionary[index1].ContainsKey(index2))
{
返回false;
}
返回true;
}
///
///等于指定的其他值。
///
///
///另一个。
///
///
///平等。
///
公共布尔等于(DoubleKeyDictionary其他)
{
if(this.OuterDictionary.Keys.Count!=other.OuterDictionary.Keys.Count)
{
返回false;
}
布尔等质量=真;
foreach(此.OuterDictionary中的var innerItems)
{
if(!other.OuterDictionary.ContainsKey(innerItems.Key))
{
isEqual=假;
}
如果(!相等)
{
打破
}
//在这里,我们可以确定关键在两个列表中,
//但是我们需要检查内部字典的内容
Dictionary otherInnerDictionary=other.OuterDictionary[innerItems.Key];
foreach(innerItems.Value中的var innerValue)
{
如果(!otherInnerDictionary.ContainsValue(innerValue.Value))
{
isEqual=假;
}
if(!otherInnerDictionary.ContainsKey(innerValue.Key))
{
isEqual=假;
}
}
如果(!相等)
{
打破
}
}
回报均等;
}
///
///获取枚举数。
///
///
///
公共IEnumerator GetEnumerator()
{
foreach(在this.OuterDictionary中为外部变量)
{
foreach(外部值中的内部变量)
{
返回新的DoubleKeyPairValue(outer.Key,inner.Key,inner.Value);
}
}
}
///
///删除指定的密钥。
///
///
///钥匙1。
///
///
///钥匙2。
///
公共无效删除(K键1,T键2)
{
this.OuterDictionary[key1].Remove(key2);
if(this.OuterDictionary[key1].Count==0)
{
this.OuterDictionary.Remove(键1);
}
}
#端区
#区域显式接口方法
///
///返回遍历集合的枚举数。
///
///
///可用于在集合中迭代的对象。
///
IEnumerator IEnumerable.GetEnumerator()
{
返回此.GetEnumerator();
}
#端区
}
///
///表示两个键和一个值。
///
///
///第一个键类型。
///
///
///第二个键类型。
///
///
///
GameObject terr = new GameObject();
foreach(Transform go in referenceTerrain.transform) {
GameObject obj = new GameObject();
GameObject origobj = go.gameObject;
obj.AddComponent<MeshRenderer>();
MeshRenderer mr = obj.GetComponent<MeshRenderer>();
mr.materials = origobj.renderer.materials;
mr.receiveShadows = origobj.renderer.receiveShadows;
mr.castShadows = origobj.renderer.castShadows;
obj.AddComponent<MeshFilter>();
MeshFilter mer = obj.GetComponent<MeshFilter>();
mer.mesh = origobj.GetComponent<MeshFilter>().mesh;
obj.AddComponent<Rigidbody>();
Rigidbody origrb = origobj.rigidbody;
Rigidbody rb = obj.rigidbody;
rb.isKinematic = origrb.isKinematic;
rb.useGravity = origrb.useGravity;
MeshCollider origmc = origobj.GetComponent<MeshCollider>();
if (origmc) {
MeshCollider mc = obj.AddComponent<MeshCollider>();
mc.sharedMesh = origmc.sharedMesh;
mc.sharedMaterial = origmc.sharedMaterial;
}
BoxCollider origbc = origobj.GetComponent<BoxCollider>();
if (origbc) {
BoxCollider bc = obj.AddComponent<BoxCollider>();
bc.sharedMaterial = origbc.sharedMaterial;
}
obj.transform.parent = terr.transform;
obj.transform.localPosition = origobj.transform.localPosition;
obj.transform.localRotation = origobj.transform.localRotation;
obj.transform.localScale = origobj.transform.localScale;
obj.SetActive(true);
}
return terr;