为什么我得到异常InvalidCastException?

时间:2014-08-12 20:02:24

标签: c# xna xna-4.0

消息:

无法将“Microsoft.Xna.Framework.Graphics.Effect”类型的对象转换为“Microsoft.Xna.Framework.Graphics.BasicEffect”

代码:

foreach (ModelMesh mesh in xwingModel.Meshes)
            {
                // This is where the mesh orientation is set, as well 
                // as our camera and projection.
                foreach (BasicEffect Effects in mesh.Effects)
                {
                    Effects.EnableDefaultLighting();
                    Effects.World = transforms[mesh.ParentBone.Index] *
                        //Matrix.CreateRotationY(modelRotation)
                         Matrix.CreateTranslation(modelPosition);
                    Effects.View = Matrix.CreateLookAt(cameraPosition,
                        Vector3.Zero, Vector3.Up);
                    Effects.Projection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f), aspectRatio,
                        1.0f, 10000.0f);
                }
                // Draw the mesh, using the effects set above.
                mesh.Draw();
            }

例外是:

BasicEffect Effects

完整的异常消息:

System.InvalidCastException was unhandled
  HResult=-2147467262
  Message=Unable to cast object of type 'Microsoft.Xna.Framework.Graphics.Effect' to type 'Microsoft.Xna.Framework.Graphics.BasicEffect'.
  Source=MyFlightSimulator
  StackTrace:
       at MyFlightSimulator.Game1.DrawModel() in Game1.cs:line 279
       at MyFlightSimulator.Game1.Draw(GameTime gameTime) in Game1.cs:line 133
       at Microsoft.Xna.Framework.Game.DrawFrame()
       at Microsoft.Xna.Framework.Game.Tick()
       at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
       at Microsoft.Xna.Framework.GameHost.OnIdle()
       at Microsoft.Xna.Framework.WindowsGameHost.RunOneFrame()
       at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
       at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at Microsoft.Xna.Framework.WindowsGameHost.Run()
       at Microsoft.Xna.Framework.Game.RunGame(Boolean useBlockingRun)
       at Microsoft.Xna.Framework.Game.Run()
       at MyFlightSimulator.Program.Main(String[] args) in Program.cs:line 15
  InnerException: 

Game1第279行是:

foreach (BasicEffect Effects in mesh.Effects)

计划第15行是:

game.Run();

这是完整的方法代码:

private void DrawModel()
        {
            Matrix[] transforms = new Matrix[xwingModel.Bones.Count];
            xwingModel.CopyAbsoluteBoneTransformsTo(transforms);

            // Draw the model. A model can have multiple meshes, so loop.
            foreach (ModelMesh mesh in xwingModel.Meshes)
            {
                // This is where the mesh orientation is set, as well 
                // as our camera and projection.
                foreach (BasicEffect Effects in mesh.Effects)
                {
                    Effects.EnableDefaultLighting();
                    Effects.World = transforms[mesh.ParentBone.Index] *
                        //Matrix.CreateRotationY(modelRotation)
                         Matrix.CreateTranslation(modelPosition);
                    Effects.View = Matrix.CreateLookAt(cameraPosition,
                        Vector3.Zero, Vector3.Up);
                    Effects.Projection = Matrix.CreatePerspectiveFieldOfView(
                        MathHelper.ToRadians(45.0f), aspectRatio,
                        1.0f, 10000.0f);
                }
                // Draw the mesh, using the effects set above.
                mesh.Draw();
            }
        }

4 个答案:

答案 0 :(得分:3)

mesh.Effects的部分或全部元素不是BasicEffect而是Effect对象

试试这个

foreach (Effect ItemEffect in mesh.Effects)
{
   if ( (ItemEffect is BasicEffect) == false)
       continue;

    BasicEffect Effects = (BasicEffect)ItemEffect;

    Effects.EnableDefaultLighting();
    Effects.World = transforms[mesh.ParentBone.Index] *

    Matrix.CreateTranslation(modelPosition);
    Effects.View = Matrix.CreateLookAt(cameraPosition,Vector3.Zero, Vector3.Up);
    Effects.Projection = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(45.0f), aspectRatio,
                    1.0f, 10000.0f);
}

答案 1 :(得分:2)

如本文所述:XNA Apply effect on BasicEffect并非所有效果都是BasicEffects。

foreach(BasicEffect basicEffect in mesh.Effects.OfType<BasicEffect>())
{

}

答案 2 :(得分:1)

mesh.Effects中包含哪些类型的对象?来自MSDN documentationBasicEffect继承自Effect,因此如果mesh.Effects中的所有元素都属于BasicEffect类型,则代码应该有效。

mesh.Effects中的元素很可能是 a BasicEffect

仔细检查该列表中的内容,或者确保只使用as运算符对BasicEffect运行代码,并检查它们是否为空,在这种情况下,是BasicEffect

foreach (BasicEffect Effects in mesh.Effects)
{
     BasicEffect basicEffect = Effects as BasicEffect;
     if (basicEffect != null)
     {
          //Effects is a BasicEffect, run code on basicEffect
     }
}

您还可以使用LINQ's OfType仅选择网格中BasicEffect s

的效果
foreach (BasicEffect Effects in mesh.Effects.OfType<BasicEffect>());
{
     //Run code on Effects
}

答案 3 :(得分:0)

并非该集合中的每个成员都可以转换为BasicEffect,但您可以避免这些:

foreach(var effect in mesh.Effects.Where(e => e.GetType().IsAssignableFrom(Effect).ToList())
    YourFunctionOrWhatever();

如果您正在阅读此内容,请检查Martijn的答案。它更漂亮:))