WinForm内嵌Unity3D
2015-11-17 17:55
706 查看
Unity3D可以C#脚本进行开,使用vstu2013.msi插件,可以实现在VS2013中的调试。在开发完成后,由于项目需要,需要将Unity3D嵌入到WinForm中。WinForm中的UnityWebPlayer Control可以载入Unity3D。先看效果图。
一、为了能够动态设置axUnityWebPlayer的Src,我使用用户控件来封装。看下面的代码。
1.增加InitUnity方法,方便外层控件调用。这里最关键的是OcxState,必须使用AxUnityWebPlayer才能依据Src动态产生。
2.动态增加进度条。
3.在实始化后对_axUnityWebPlayer进行隐藏,同时启动进度条,并绑定Unity的回调事件OnExternalCall。在OnExternalCall事件中,监听Unity发来的LOAD_COMPLETE值,然后判断是否显示_axUnityWebPlayer.
4.为了能让外层也收到Unity发来的消息,使用委托二次实现了OnExternalCall,也就是OnUnityCall方法。
5.SendMessage的实现,第一个参数为Unity中的对象名称,第二个参数为Unity脚本中的方法,第三个参数是传送的值(仅限于int、string,其他的会失败或者异常)。
6.继承IMessageFilter接口,捕获消息,然后过滤_axUnityWebPlayer区域内产生的鼠标右键消息,同时增加DisableMouseRight属性来控制。
7.一定要将项目调成x86的模式,否则会报“没有注册类XXX”的信息。
8.axUnityWebPlayer控件需要在工具箱中添加,如下图。
二、窗体界面的代码
1.CallUnity是响应WinForm发来消息的函数。
2.Application.ExternalCall是向WinForm发出消息,第一参数是函数的名称,第二个之后的参数是函数的参数。
四、Unity3D要在WebPlayer模式下编译
转载请注明出处
代码下载http://download.csdn.net/detail/xxdddail/9277447
一、为了能够动态设置axUnityWebPlayer的Src,我使用用户控件来封装。看下面的代码。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; using System.Threading; namespace UnityHost { public partial class U3DPlayer : UserControl, IMessageFilter { #region 属性 private String _src; /// <summary> /// Unity3D文件的路径 /// </summary> public String Src { get { return _src; } private set { _src = value; } } private bool _disableMouseRight = true; /// <summary> /// 禁用鼠标右键 /// </summary> public bool DisableMouseRight { get { return _disableMouseRight; } set { _disableMouseRight = value; } } #endregion #region 自定义事件 //委托 public delegate void ExternalCallHandler(object sender, AxUnityWebPlayerAXLib._DUnityWebPlayerAXEvents_OnExternalCallEvent e); /// <summary> /// 接收Unity调用宿主函数的消息 /// </summary> [Browsable(true), Description("接收Unity调用宿主(如WinForm)函数的消息")] public event ExternalCallHandler UnityCall; //方法 public void OnUnityCall(object sender, AxUnityWebPlayerAXLib._DUnityWebPlayerAXEvents_OnExternalCallEvent e) { if (UnityCall != null) { UnityCall(sender, e); } } #endregion #region 内部变量 private AxUnityWebPlayerAXLib.AxUnityWebPlayer _axUnityWebPlayer=null; private ProgressBar _progressBarLoad=null; #endregion public U3DPlayer() { InitializeComponent(); InitProgressBar(); } private void InitProgressBar() { if (_progressBarLoad == null) { _progressBarLoad = new ProgressBar(); _progressBarLoad.Height = 100; _progressBarLoad.Style = ProgressBarStyle.Marquee; _progressBarLoad.Top = (this.Height - _progressBarLoad.Height) / 2; Controls.Add(_progressBarLoad); } } #region InitUnity /// <summary> /// 初始化UnityWebPlayer /// </summary> /// <param name="src">Unity3D文件的路径</param> public void InitUnity(String src) { Src = src; if (!File.Exists(Src)) { return; } var unity = new AxUnityWebPlayerAXLib.AxUnityWebPlayer(); ((System.ComponentModel.ISupportInitialize)(unity)).BeginInit(); Controls.Add(unity); ((System.ComponentModel.ISupportInitialize)(unity)).EndInit(); unity.src = Src;//Application.StartupPath + "\\u.unity3d"; //改成自己想要的路径 AxHost.State state = unity.OcxState; Controls.Remove(unity); unity.Dispose(); unity = new AxUnityWebPlayerAXLib.AxUnityWebPlayer(); ((System.ComponentModel.ISupportInitialize)(unity)).BeginInit(); this.SuspendLayout(); unity.Dock = DockStyle.Fill; //unity.Name = "Unity"; unity.OcxState = state; unity.TabIndex = 0; this.Controls.Add(unity); //panel1是我用的一个容器,改成this.Controls也可以 ((System.ComponentModel.ISupportInitialize)(unity)).EndInit(); this.ResumeLayout(false); _axUnityWebPlayer = unity; if (_axUnityWebPlayer == null) { throw new Exception("_axUnityWebPlayer init fail"); } else { _axUnityWebPlayer.OnExternalCall += _axUnityWebPlayer_OnExternalCall; _axUnityWebPlayer.Hide(); ShowProgressBar(); } } #endregion #region 进度条 private void ShowProgressBar() { _progressBarLoad.Visible = true; _progressBarLoad.Left = 0; _progressBarLoad.Width = this.Width; } private void HideProgressBar() { if (_progressBarLoad!=null) { _progressBarLoad.Visible = false; } } #endregion void _axUnityWebPlayer_OnExternalCall(object sender, AxUnityWebPlayerAXLib._DUnityWebPlayerAXEvents_OnExternalCallEvent e) { if (e.value.StartsWith("LOAD_COMPLETE")) { if (!_axUnityWebPlayer.Visible) { _axUnityWebPlayer.Width = this.Width; _axUnityWebPlayer.Height = this.Height; _axUnityWebPlayer.Show(); HideProgressBar(); } } OnUnityCall(sender, e); } private void U3DPlayer_Load(object sender, EventArgs e) { Graphics g = this.CreateGraphics(); g.Clear(this.BackColor); if (DisableMouseRight) { Application.AddMessageFilter(this); this.Disposed += U3DPlayer_Disposed; } } void U3DPlayer_Disposed(object sender, EventArgs e) { if (DisableMouseRight) { Application.RemoveMessageFilter(this); } } #region SendMessage /// <summary> /// 发送消息给Unity /// </summary> /// <param name="unityObjName">Unity中的对象名称</param> /// <param name="unityScriptyMethod">Unity脚本中的方法</param> /// <param name="val">传送的值.仅限于int、float、string</param> public void SendMessage(string unityObjName, string unityScriptyMethod, object val) { if (_axUnityWebPlayer == null) { return; } _axUnityWebPlayer.SendMessage(unityObjName, unityScriptyMethod, val); } #endregion private void U3DPlayer_MouseDown(object sender, MouseEventArgs e) { } /// <summary> /// 过滤鼠标右键 /// </summary> /// <param name="m"></param> /// <returns></returns> public bool PreFilterMessage(ref System.Windows.Forms.Message m) { if (_axUnityWebPlayer == null) { return false; } const int WM_RBUTTONDOWN = 0x204; const int WM_RBUTTONUP = 0x205; const int WM_RBUTTONDBLCLK = 0x206; // 屏蔽右键消息区域。 System.Drawing.Rectangle my_Area = new System.Drawing.Rectangle(_axUnityWebPlayer.Location, _axUnityWebPlayer.Size); if (my_Area.Contains(this.PointToClient(Control.MousePosition))) { switch (m.Msg) { case WM_RBUTTONDOWN: return true; case WM_RBUTTONUP: return true; case WM_RBUTTONDBLCLK: return true; default: return false; } } return false; } } }注:代码中还实现了其他的功能,如下
1.增加InitUnity方法,方便外层控件调用。这里最关键的是OcxState,必须使用AxUnityWebPlayer才能依据Src动态产生。
2.动态增加进度条。
3.在实始化后对_axUnityWebPlayer进行隐藏,同时启动进度条,并绑定Unity的回调事件OnExternalCall。在OnExternalCall事件中,监听Unity发来的LOAD_COMPLETE值,然后判断是否显示_axUnityWebPlayer.
4.为了能让外层也收到Unity发来的消息,使用委托二次实现了OnExternalCall,也就是OnUnityCall方法。
5.SendMessage的实现,第一个参数为Unity中的对象名称,第二个参数为Unity脚本中的方法,第三个参数是传送的值(仅限于int、string,其他的会失败或者异常)。
6.继承IMessageFilter接口,捕获消息,然后过滤_axUnityWebPlayer区域内产生的鼠标右键消息,同时增加DisableMouseRight属性来控制。
7.一定要将项目调成x86的模式,否则会报“没有注册类XXX”的信息。
8.axUnityWebPlayer控件需要在工具箱中添加,如下图。
二、窗体界面的代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace UnityHost { public partial class FormHost : Form { public FormHost() { InitializeComponent(); } private void buttonSendToUnity_Click(object sender, EventArgs e) { String info = textBoxSendMessage.Text; if (String.IsNullOrWhiteSpace(info)) { MessageBox.Show("请输入内容"); return; } u3DPlayer1.SendMessage("Main Camera", "CallUnity", info); } private void FormHost_Load(object sender, EventArgs e) { String src = Application.StartupPath + "\\UnityWeb\\UnityWeb.unity3d"; u3DPlayer1.InitUnity(src); } private void u3DPlayer1_UnityCall(object sender, AxUnityWebPlayerAXLib._DUnityWebPlayerAXEvents_OnExternalCallEvent e) { this.Text = "收到Unity的消息:" + e.value; } } }三、Unity3D的C#脚本
using UnityEngine; using System.Collections; using System; public class Main : MonoBehaviour { private string _messageReceive = string.Empty; private bool _isButtonClick = false; private int _notifyTimeAfterLoadComplete = 3; // Use this for initialization void Start() { } // Update is called once per frame void Update() { } void OnGUI() { if (GUI.Button(new Rect(100, 10, 80, 20), "测试")) { _isButtonClick = !_isButtonClick; } GUI.Label(new Rect(50, 30, 150, 30), _messageReceive); if (_isButtonClick) { Application.ExternalCall("ToWinform", Guid.NewGuid().ToString()); _isButtonClick = false; } if (_notifyTimeAfterLoadComplete>0) { Application.ExternalCall("LOAD_COMPLETE", ""); _notifyTimeAfterLoadComplete--; } } void CallUnity(object val) { _messageReceive = string.Format("{0}", val); } }注:
1.CallUnity是响应WinForm发来消息的函数。
2.Application.ExternalCall是向WinForm发出消息,第一参数是函数的名称,第二个之后的参数是函数的参数。
四、Unity3D要在WebPlayer模式下编译
转载请注明出处
代码下载http://download.csdn.net/detail/xxdddail/9277447
相关文章推荐
- Unity中 gameObject的顶点捕捉
- Unity3D自定义脚本模板
- 学习Space shooter 小项目 总结
- unity 网格Mesh占用内存公式
- 【Unity开发】Unity2D多分辨率屏幕适配方案(IOS露出天空盒解决办法)
- Unity加载prefab时调用脚本函数顺序和内存释放问题
- Unity3d中设置UISprite图片灰显方法
- Unity3D占用内存太大的解决方法
- Unity给力插件之MegaFiers
- 【UGUI】Unity的UGUI实现Button按钮长按状态的判断
- UnityEngine.UI.dll is in timestamps but is not known in assetdatabase
- unity 手游《天神传》服务端源码+客户端源码+文档
- Unity3d 开发之 ulua 坑的总结
- Unity 实现Log实时输出到屏幕或控制台上<二>
- Unity 实现Log实时输出到屏幕或控制台上<二>
- unity物体指示线
- Unity拖动摄像机加上惯性滑动的效果
- 【NGUI】Unity插件NGUI的Button按钮修改为Disabled状态
- unity导入的自定义3D模型从地板掉下去
- Unity 配置使 .prefab 可以文本化阅读修改