让GameObject正确“附加”?

时间:2016-03-02 17:35:45

标签: c# unity3d

这个脚本使一个立方体“坚持”它碰到的任何东西。问题在于,当它以相对较高或较高的速度运行时(或者当设备本身速度较慢时),立方体往往会“碰到”它碰撞的内部然后坚持下去。我需要做些什么改变才能解决这个问题?

为了使这个脚本有效,一个GameObject必须有bool _sticksToObjects = true;而另一个bool _sticksToObjects = false;

我尝试将Rigidbody的{​​{1}}模式转为Collision DetectionContinuous

我认为我的脚本取决于帧速率。这可能是问题所在。

正常“附加”:

enter image description here

异常“附加”:

enter image description here

Continuous Dynamic

以下是Unity编辑器的一些屏幕截图:

enter image description here

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:6)

这是游戏工程中众所周知的一类问题,您会很高兴知道解决方案相对简单。您会很高兴听到有类似但更复杂的问题以同样的方式实际解决。我试着解释一下。

现在就是这样。经常出现以下问题......

  

所以我正在开发GTA。我有一个人形,H,跑来跑去。她接近车辆V.她打开车门进入并开走。之后,一切都在Mecanim中下地狱,所有代码都停止工作。怎么办?

令人惊讶的是,游戏的方式是:

令人惊讶的是:你实际上在那时交换到完全不同的模型!!!!!

游戏中你有H和V.但是你有一个动画(比方说)让H爬到V.然后,你真的会破坏H和V的游戏对象,实例化(或者只是唤醒)一个新的,完全不同的游戏对象,这是D("一辆由女士驾驶的汽车")。

(如果你考虑一下,你可以看到,当你这样做时,你仔细调整D中的所有内容,以便匹配什么是"然后发生&#34 ;在框架中,相对于H和V.例如,从字面上看,你将汽车V的变换,扭曲等复制到新车里面D,如果女士H有SmearedMakeupEffect,你把对于Lady-in-D中的SmearedMakeupEffect,你可以完全相同地定位所有骨骼,依此类推。)

另一个简单的例子是,你常常让人们问,"我的角色C被杀了,我希望它变成一个布娃娃,怎么样?"事实上,你只是交换到一个全新的游戏对象,你已经为游戏的那一段做好了准备。事实上,如果你在游戏中有一个角色A(" Arnie"),那么你有4或5个不同的As"是正常的。坐在舞台上,所以,那里有布拉格A"," A可以跳舞" " A with weapon"。事实上,其中很多都是组合,你知道" A on the horse" " A在车里"等等。

有趣的是,"真实"这里的解决方案是,

一旦它们成为新的连接物,就将它们摧毁并交换成一个新的游戏对象!

如果你已经制作了游戏"直到你脸红了#34;从制作游戏开始,这就是你要做的事情。即使它的'一个简单的情况,从长远来看,它更容易。毕竟,考虑发生这种情况时你必须做的所有事情:

  1. 让对方的孩子击中对象

  2. 关闭孩子的物理

  3. 改变物理对整个事物的工作方式

  4. 关闭或更改击球对象上的对手,可能使其成为整体对象的一部分

  5. 你可能会有某种新的"分离"它可以被淘汰的物理学 - 你必须把所有这些都打开

  6. 可能会改变声音效果,颜色等小问题

  7. 正如你所看到的那样,做这些事情是一项繁重的苦差事,而且事实上它只是其中一件事,它更容易做得更好。"并改为新模型。

    所有这一切,我知道你想要一个快速脚本解决方案,你可以粘贴:)这里是......

    第0步,您将创建" YourScript"继续"主要"立方体。它会"赶上"另一个立方体四处走动。

    YourScript看起来基本上就像这样...

       [System.NonSerialized] public bool isConnectedNow;
       void OnCollisionEnter(Collision collision)
          GameObject theThingWeCaught = collision.gameObject
          Debug.Log("We caught this thing .. " + theThingWeCaught.name)
          // make it a child of us......
          theThingWeCaught.transform.parent = transform
          theThingWeCaught ... set kinematic
          theThingWeCaught ... probably disable the rigidbody
          theThingWeCaught ... probably disable the collider
          isConnectedNow = true;
    

    你真的需要做的就是这些。

    第1步,您的脚本必须有public bool这样的

     [System.NonSerialized] public bool isConnectedNow;
    

    第2步,这里的MyScript进入击中立方体,首先我们将对你的isConnectedNow布尔工作进行单元测试

    public Class MyScript:MonoBehaviour // attach to the "child" cube
     {
     public float correctXDistance;
     public float correctYDistance;
     public Transform bigCube;
     public YourScript yourScript;
    
     void Update()
      {
      string message = yourScript.isConnectedNow ? "free" : "stuck";
      Debug.Log("I am " + message);
      }
     }
    

    附加,调试和运行。让小立方体棒并从大立方体中取出来。观察控制台。有用?所以将其添加到MyScript

    private void DistanceCorrectionX()
     {
     float xDistance = bigCube.position.x - transform.position.x;
     float xSign = Mathf.Sign(xDistance);
     float xDelta = Mathf.Abs(xDistance);
     float closenessPercentage = (xDelta/correctXDistance)*100f;
     if ( closenessPercentage<90f || closenessPercentage>110f)
        {
        // they are not close enough to quantize on this axis
        // this comes in to play when you have multiple axes
        return;  // do nothing.
        }
     float xShouldBe = bigCube.position.x + xSign * correctXDistance;
     Vector3 p = transform;
     p.x = xShouldBe; // be careful it's .y, .z etc for other axes
     transform.position = p;
     }
    

    现在在MyScript中的Update()中调用它,就像这样

     void Update()
      {
      Debug.Log("I am " yourScript.isConnectedNow ? "free" : "stuck");
      if (yourScript.isConnectedNow) DistanceCorrectionX();
      }
    

    现在实际上玩并坚持下去。现在,因为它在Update中运行,只需在Play中查看Inspector MyScript调整correctXDistance 的值以获得您想要的精确外观。当你决定一个值时,unPlay并将其作为你想要的最终值。

    接下来,在DistanceCorrectionX中,只需复制所有代码,然后再次为Y轴DistanceCorrectionX执行此操作。如果你也做Z,那就去做吧。

    最后。请注意,您将拥有许多混乱的代码,例如......

     void Update()
      {
      // handle all the DistanceCorrectionX etc as seen above.
    
      if (yourScript.isConnectedNow)
          {
          .. turn off the collider on me
          }
      else
          {
          .. turn on the collider on me
          }
      }
    

    等等,有很多小东西&#34;你需要做的。

    不要忘记,绝大多数情况下,根据您的具体情况,您可能希望让击球对象成为的大对象的孩子。 (当然,他们会作为一个整体一起四处走动。)

    请注意,在上面的定位代码中,我只是将其显示为位置,而不是本地位置,以获得教学清晰度。如果你想让它们四处乱窜,旋转等等,你可以让击球对象成为另一个对象的孩子,你会以同样的方式使用localPosition。享受。

答案 1 :(得分:1)

我想到的一种可能方式是:

在“碰撞输入”的内部,检查这些物体之间的距离,并移动那个应该粘在另一个物体上的物体。

如图所示,A和B之间的距离应等于宽度之和除以2(当然,阈值较小)。 如果距离小于宽度/ 2的总和,那么你有一个异常的“附着”,你必须移走其中一个物体。实现这一点并不困难。

enter image description here