aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-04-03 05:50:13 +0100
committerJustin Clark-Casey (justincc)2012-04-03 05:51:38 +0100
commit746829967315cc82560a855a4772e45888bf8fbe (patch)
tree1e21d5c27101cb505a4ac4bcdf6e356f2e409d52 /OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
parentImplement bulk inventory update over CAPS (not recursive by design, (diff)
downloadopensim-SC-746829967315cc82560a855a4772e45888bf8fbe.zip
opensim-SC-746829967315cc82560a855a4772e45888bf8fbe.tar.gz
opensim-SC-746829967315cc82560a855a4772e45888bf8fbe.tar.bz2
opensim-SC-746829967315cc82560a855a4772e45888bf8fbe.tar.xz
Eliminate race condition where many callers would check SOP.PhysicsActor != null then assume it was still not null in later code.
Another thread could come and turn off physics for a part (null PhysicsActor) at any point. Had to turn off localCopy on warp3D CoreModules section in prebuild.xml since on current nant this copies all DLLs in bin/ which can be a very large number with compiled DLLs No obvious reason for doing that copy - nothing else does it.
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs207
1 files changed, 116 insertions, 91 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 439b718..2b1fba0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -151,6 +151,14 @@ namespace OpenSim.Region.Framework.Scenes
151 public int[] PayPrice = {-2,-2,-2,-2,-2}; 151 public int[] PayPrice = {-2,-2,-2,-2,-2};
152 152
153 [XmlIgnore] 153 [XmlIgnore]
154 /// <summary>
155 /// The representation of this part in the physics scene.
156 /// </summary>
157 /// <remarks>
158 /// If you use this property more than once in a section of code then you must take a reference and use that.
159 /// If another thread is simultaneously turning physics off on this part then this refernece could become
160 /// null at any time.
161 /// </remarks>
154 public PhysicsActor PhysActor 162 public PhysicsActor PhysActor
155 { 163 {
156 get { return m_physActor; } 164 get { return m_physActor; }
@@ -522,10 +530,11 @@ namespace OpenSim.Region.Framework.Scenes
522 set 530 set
523 { 531 {
524 m_name = value; 532 m_name = value;
525 if (PhysActor != null) 533
526 { 534 PhysicsActor pa = PhysActor;
527 PhysActor.SOPName = value; 535
528 } 536 if (pa != null)
537 pa.SOPName = value;
529 } 538 }
530 } 539 }
531 540
@@ -535,10 +544,11 @@ namespace OpenSim.Region.Framework.Scenes
535 set 544 set
536 { 545 {
537 m_material = (Material)value; 546 m_material = (Material)value;
538 if (PhysActor != null) 547
539 { 548 PhysicsActor pa = PhysActor;
540 PhysActor.SetMaterial((int)value); 549
541 } 550 if (pa != null)
551 pa.SetMaterial((int)value);
542 } 552 }
543 } 553 }
544 554
@@ -669,9 +679,7 @@ namespace OpenSim.Region.Framework.Scenes
669 // If this is a linkset, we don't want the physics engine mucking up our group position here. 679 // If this is a linkset, we don't want the physics engine mucking up our group position here.
670 PhysicsActor actor = PhysActor; 680 PhysicsActor actor = PhysActor;
671 if (actor != null && ParentID == 0) 681 if (actor != null && ParentID == 0)
672 {
673 m_groupPosition = actor.Position; 682 m_groupPosition = actor.Position;
674 }
675 683
676 if (ParentGroup.IsAttachment) 684 if (ParentGroup.IsAttachment)
677 { 685 {
@@ -979,7 +987,7 @@ namespace OpenSim.Region.Framework.Scenes
979 if (Shape.SculptEntry) 987 if (Shape.SculptEntry)
980 CheckSculptAndLoad(); 988 CheckSculptAndLoad();
981 else 989 else
982 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 990 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
983 } 991 }
984 } 992 }
985 } 993 }
@@ -1505,12 +1513,14 @@ namespace OpenSim.Region.Framework.Scenes
1505 } 1513 }
1506 1514
1507 // Basic Physics can also return null as well as an exception catch. 1515 // Basic Physics can also return null as well as an exception catch.
1508 if (PhysActor != null) 1516 PhysicsActor pa = PhysActor;
1517
1518 if (pa != null)
1509 { 1519 {
1510 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 1520 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1511 PhysActor.SetMaterial(Material); 1521 pa.SetMaterial(Material);
1512 DoPhysicsPropertyUpdate(RigidBody, true); 1522 DoPhysicsPropertyUpdate(RigidBody, true);
1513 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1523 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1514 } 1524 }
1515 } 1525 }
1516 } 1526 }
@@ -1731,23 +1741,25 @@ namespace OpenSim.Region.Framework.Scenes
1731 } 1741 }
1732 else 1742 else
1733 { 1743 {
1734 if (PhysActor != null) 1744 PhysicsActor pa = PhysActor;
1745
1746 if (pa != null)
1735 { 1747 {
1736 if (UsePhysics != PhysActor.IsPhysical || isNew) 1748 if (UsePhysics != pa.IsPhysical || isNew)
1737 { 1749 {
1738 if (PhysActor.IsPhysical) // implies UsePhysics==false for this block 1750 if (pa.IsPhysical) // implies UsePhysics==false for this block
1739 { 1751 {
1740 if (!isNew) 1752 if (!isNew)
1741 ParentGroup.Scene.RemovePhysicalPrim(1); 1753 ParentGroup.Scene.RemovePhysicalPrim(1);
1742 1754
1743 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1744 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; 1756 pa.OnOutOfBounds -= PhysicsOutOfBounds;
1745 PhysActor.delink(); 1757 pa.delink();
1746 1758
1747 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew))
1748 { 1760 {
1749 // destroy all joints connected to this now deactivated body 1761 // destroy all joints connected to this now deactivated body
1750 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor); 1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
1751 } 1763 }
1752 1764
1753 // stop client-side interpolation of all joint proxy objects that have just been deleted 1765 // stop client-side interpolation of all joint proxy objects that have just been deleted
@@ -1766,7 +1778,7 @@ namespace OpenSim.Region.Framework.Scenes
1766 //RotationalVelocity = new Vector3(0, 0, 0); 1778 //RotationalVelocity = new Vector3(0, 0, 0);
1767 } 1779 }
1768 1780
1769 PhysActor.IsPhysical = UsePhysics; 1781 pa.IsPhysical = UsePhysics;
1770 1782
1771 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves.
1772 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
@@ -1779,13 +1791,15 @@ namespace OpenSim.Region.Framework.Scenes
1779 { 1791 {
1780 ParentGroup.Scene.AddPhysicalPrim(1); 1792 ParentGroup.Scene.AddPhysicalPrim(1);
1781 1793
1782 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 1794 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1783 PhysActor.OnOutOfBounds += PhysicsOutOfBounds; 1795 pa.OnOutOfBounds += PhysicsOutOfBounds;
1784 if (ParentID != 0 && ParentID != LocalId) 1796 if (ParentID != 0 && ParentID != LocalId)
1785 { 1797 {
1786 if (ParentGroup.RootPart.PhysActor != null) 1798 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1799
1800 if (parentPa != null)
1787 { 1801 {
1788 PhysActor.link(ParentGroup.RootPart.PhysActor); 1802 pa.link(parentPa);
1789 } 1803 }
1790 } 1804 }
1791 } 1805 }
@@ -1797,7 +1811,7 @@ namespace OpenSim.Region.Framework.Scenes
1797 if (Shape.SculptEntry) 1811 if (Shape.SculptEntry)
1798 CheckSculptAndLoad(); 1812 CheckSculptAndLoad();
1799 else 1813 else
1800 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 1814 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
1801 } 1815 }
1802 } 1816 }
1803 } 1817 }
@@ -1908,24 +1922,30 @@ namespace OpenSim.Region.Framework.Scenes
1908 1922
1909 public Vector3 GetGeometricCenter() 1923 public Vector3 GetGeometricCenter()
1910 { 1924 {
1911 if (PhysActor != null) 1925 PhysicsActor pa = PhysActor;
1912 return new Vector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); 1926
1927 if (pa != null)
1928 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z);
1913 else 1929 else
1914 return new Vector3(0, 0, 0); 1930 return new Vector3(0, 0, 0);
1915 } 1931 }
1916 1932
1917 public float GetMass() 1933 public float GetMass()
1918 { 1934 {
1919 if (PhysActor != null) 1935 PhysicsActor pa = PhysActor;
1920 return PhysActor.Mass; 1936
1937 if (pa != null)
1938 return pa.Mass;
1921 else 1939 else
1922 return 0; 1940 return 0;
1923 } 1941 }
1924 1942
1925 public Vector3 GetForce() 1943 public Vector3 GetForce()
1926 { 1944 {
1927 if (PhysActor != null) 1945 PhysicsActor pa = PhysActor;
1928 return PhysActor.Force; 1946
1947 if (pa != null)
1948 return pa.Force;
1929 else 1949 else
1930 return Vector3.Zero; 1950 return Vector3.Zero;
1931 } 1951 }
@@ -2556,9 +2576,11 @@ namespace OpenSim.Region.Framework.Scenes
2556 2576
2557 public void PhysicsRequestingTerseUpdate() 2577 public void PhysicsRequestingTerseUpdate()
2558 { 2578 {
2559 if (PhysActor != null) 2579 PhysicsActor pa = PhysActor;
2580
2581 if (pa != null)
2560 { 2582 {
2561 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); 2583 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2562 2584
2563 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2585 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2564 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2586 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
@@ -2570,6 +2592,7 @@ namespace OpenSim.Region.Framework.Scenes
2570 } 2592 }
2571 //ParentGroup.RootPart.m_groupPosition = newpos; 2593 //ParentGroup.RootPart.m_groupPosition = newpos;
2572 } 2594 }
2595
2573 ScheduleTerseUpdate(); 2596 ScheduleTerseUpdate();
2574 } 2597 }
2575 2598
@@ -2660,7 +2683,9 @@ namespace OpenSim.Region.Framework.Scenes
2660 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); 2683 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
2661 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); 2684 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
2662 2685
2663 if (PhysActor != null && PhysActor.IsPhysical) 2686 PhysicsActor pa = PhysActor;
2687
2688 if (pa != null && pa.IsPhysical)
2664 { 2689 {
2665 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); 2690 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys);
2666 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); 2691 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
@@ -2809,12 +2834,14 @@ namespace OpenSim.Region.Framework.Scenes
2809 m_shape.SculptData = texture.Data; 2834 m_shape.SculptData = texture.Data;
2810 } 2835 }
2811 2836
2812 if (PhysActor != null) 2837 PhysicsActor pa = PhysActor;
2838
2839 if (pa != null)
2813 { 2840 {
2814 // Update the physics actor with the new loaded sculpt data and set the taint signal. 2841 // Update the physics actor with the new loaded sculpt data and set the taint signal.
2815 PhysActor.Shape = m_shape; 2842 pa.Shape = m_shape;
2816 2843
2817 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 2844 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
2818 } 2845 }
2819 } 2846 }
2820 } 2847 }
@@ -3072,10 +3099,10 @@ namespace OpenSim.Region.Framework.Scenes
3072 3099
3073 public void SetBuoyancy(float fvalue) 3100 public void SetBuoyancy(float fvalue)
3074 { 3101 {
3075 if (PhysActor != null) 3102 PhysicsActor pa = PhysActor;
3076 { 3103
3077 PhysActor.Buoyancy = fvalue; 3104 if (pa != null)
3078 } 3105 pa.Buoyancy = fvalue;
3079 } 3106 }
3080 3107
3081 public void SetDieAtEdge(bool p) 3108 public void SetDieAtEdge(bool p)
@@ -3088,57 +3115,50 @@ namespace OpenSim.Region.Framework.Scenes
3088 3115
3089 public void SetFloatOnWater(int floatYN) 3116 public void SetFloatOnWater(int floatYN)
3090 { 3117 {
3091 if (PhysActor != null) 3118 PhysicsActor pa = PhysActor;
3092 { 3119
3093 if (floatYN == 1) 3120 if (pa != null)
3094 { 3121 pa.FloatOnWater = floatYN == 1;
3095 PhysActor.FloatOnWater = true;
3096 }
3097 else
3098 {
3099 PhysActor.FloatOnWater = false;
3100 }
3101 }
3102 } 3122 }
3103 3123
3104 public void SetForce(Vector3 force) 3124 public void SetForce(Vector3 force)
3105 { 3125 {
3106 if (PhysActor != null) 3126 PhysicsActor pa = PhysActor;
3107 { 3127
3108 PhysActor.Force = force; 3128 if (pa != null)
3109 } 3129 pa.Force = force;
3110 } 3130 }
3111 3131
3112 public void SetVehicleType(int type) 3132 public void SetVehicleType(int type)
3113 { 3133 {
3114 if (PhysActor != null) 3134 PhysicsActor pa = PhysActor;
3115 { 3135
3116 PhysActor.VehicleType = type; 3136 if (pa != null)
3117 } 3137 pa.VehicleType = type;
3118 } 3138 }
3119 3139
3120 public void SetVehicleFloatParam(int param, float value) 3140 public void SetVehicleFloatParam(int param, float value)
3121 { 3141 {
3122 if (PhysActor != null) 3142 PhysicsActor pa = PhysActor;
3123 { 3143
3124 PhysActor.VehicleFloatParam(param, value); 3144 if (pa != null)
3125 } 3145 pa.VehicleFloatParam(param, value);
3126 } 3146 }
3127 3147
3128 public void SetVehicleVectorParam(int param, Vector3 value) 3148 public void SetVehicleVectorParam(int param, Vector3 value)
3129 { 3149 {
3130 if (PhysActor != null) 3150 PhysicsActor pa = PhysActor;
3131 { 3151
3132 PhysActor.VehicleVectorParam(param, value); 3152 if (pa != null)
3133 } 3153 pa.VehicleVectorParam(param, value);
3134 } 3154 }
3135 3155
3136 public void SetVehicleRotationParam(int param, Quaternion rotation) 3156 public void SetVehicleRotationParam(int param, Quaternion rotation)
3137 { 3157 {
3138 if (PhysActor != null) 3158 PhysicsActor pa = PhysActor;
3139 { 3159
3140 PhysActor.VehicleRotationParam(param, rotation); 3160 if (pa != null)
3141 } 3161 pa.VehicleRotationParam(param, rotation);
3142 } 3162 }
3143 3163
3144 /// <summary> 3164 /// <summary>
@@ -4226,6 +4246,8 @@ namespace OpenSim.Region.Framework.Scenes
4226 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4246 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4227 return; 4247 return;
4228 4248
4249 PhysicsActor pa = PhysActor;
4250
4229 // Special cases for VD. VD can only be called from a script 4251 // Special cases for VD. VD can only be called from a script
4230 // and can't be combined with changes to other states. So we can rely 4252 // and can't be combined with changes to other states. So we can rely
4231 // that... 4253 // that...
@@ -4241,8 +4263,9 @@ namespace OpenSim.Region.Framework.Scenes
4241 { 4263 {
4242 SetVD = false; // Switch it of for the course of this routine 4264 SetVD = false; // Switch it of for the course of this routine
4243 VolumeDetectActive = false; // and also permanently 4265 VolumeDetectActive = false; // and also permanently
4244 if (PhysActor != null) 4266
4245 PhysActor.SetVolumeDetect(0); // Let physics know about it too 4267 if (pa != null)
4268 pa.SetVolumeDetect(0); // Let physics know about it too
4246 } 4269 }
4247 else 4270 else
4248 { 4271 {
@@ -4357,9 +4380,9 @@ namespace OpenSim.Region.Framework.Scenes
4357 // Defensive programming calls for a check here. 4380 // Defensive programming calls for a check here.
4358 // Better would be throwing an exception that could be catched by a unit test as the internal 4381 // Better would be throwing an exception that could be catched by a unit test as the internal
4359 // logic should make sure, this Physactor is always here. 4382 // logic should make sure, this Physactor is always here.
4360 if (this.PhysActor != null) 4383 if (pa != null)
4361 { 4384 {
4362 PhysActor.SetVolumeDetect(1); 4385 pa.SetVolumeDetect(1);
4363 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4386 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4364 this.VolumeDetectActive = true; 4387 this.VolumeDetectActive = true;
4365 } 4388 }
@@ -4368,11 +4391,8 @@ namespace OpenSim.Region.Framework.Scenes
4368 { 4391 {
4369 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4392 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4370 // (mumbles, well, at least if you have infinte CPU powers :-)) 4393 // (mumbles, well, at least if you have infinte CPU powers :-))
4371 PhysicsActor pa = this.PhysActor;
4372 if (pa != null) 4394 if (pa != null)
4373 {
4374 PhysActor.SetVolumeDetect(0); 4395 PhysActor.SetVolumeDetect(0);
4375 }
4376 4396
4377 this.VolumeDetectActive = false; 4397 this.VolumeDetectActive = false;
4378 } 4398 }
@@ -4385,6 +4405,7 @@ namespace OpenSim.Region.Framework.Scenes
4385 { 4405 {
4386 RemFlag(PrimFlags.TemporaryOnRez); 4406 RemFlag(PrimFlags.TemporaryOnRez);
4387 } 4407 }
4408
4388 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4409 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4389 4410
4390 if (ParentGroup != null) 4411 if (ParentGroup != null)
@@ -4453,10 +4474,12 @@ namespace OpenSim.Region.Framework.Scenes
4453 m_shape.PathTwist = shapeBlock.PathTwist; 4474 m_shape.PathTwist = shapeBlock.PathTwist;
4454 m_shape.PathTwistBegin = shapeBlock.PathTwistBegin; 4475 m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
4455 4476
4456 if (PhysActor != null) 4477 PhysicsActor pa = PhysActor;
4478
4479 if (pa != null)
4457 { 4480 {
4458 PhysActor.Shape = m_shape; 4481 pa.Shape = m_shape;
4459 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 4482 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4460 } 4483 }
4461 4484
4462 // This is what makes vehicle trailers work 4485 // This is what makes vehicle trailers work
@@ -4598,6 +4621,8 @@ namespace OpenSim.Region.Framework.Scenes
4598 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4621 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4599 } 4622 }
4600 4623
4624 PhysicsActor pa = PhysActor;
4625
4601 if ( 4626 if (
4602 ((AggregateScriptEvents & scriptEvents.collision) != 0) || 4627 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4603 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || 4628 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
@@ -4609,18 +4634,18 @@ namespace OpenSim.Region.Framework.Scenes
4609 ) 4634 )
4610 { 4635 {
4611 // subscribe to physics updates. 4636 // subscribe to physics updates.
4612 if (PhysActor != null) 4637 if (pa != null)
4613 { 4638 {
4614 PhysActor.OnCollisionUpdate += PhysicsCollision; 4639 pa.OnCollisionUpdate += PhysicsCollision;
4615 PhysActor.SubscribeEvents(1000); 4640 pa.SubscribeEvents(1000);
4616 } 4641 }
4617 } 4642 }
4618 else 4643 else
4619 { 4644 {
4620 if (PhysActor != null) 4645 if (pa != null)
4621 { 4646 {
4622 PhysActor.UnSubscribeEvents(); 4647 pa.UnSubscribeEvents();
4623 PhysActor.OnCollisionUpdate -= PhysicsCollision; 4648 pa.OnCollisionUpdate -= PhysicsCollision;
4624 } 4649 }
4625 } 4650 }
4626 4651