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&lt;K, T, V&gt;"/> 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&lt;K, T, V&gt;"/> 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;