周末学习了下HybridCLR的原理和用法做了个FlyBrid小demo。记录一下
官网里写的原理:
对于这个我的理解是:
Unity引擎的代码使用还是AOT方式。对于项目业务这块打成多个程序集。运行时使用了解释器,解释执行。从而完成热更新。
一。环境安装
工作安装HyBridClr包如图
工程改成IL2CPP模式(如果报错,安装Unity对应平台的IL2CPP包)
点击多出来的菜单中的HyBrid的Install按钮进行环境安装。
二。Demo制作
看作者所说,这个工具如果是Prefab上挂脚本的方式,需要打成AssetBundle方式或者是项目运行时动态加载才能起到效果。这里我就使用第一种方式。
项目写的比较简单就贴一点关键代码吧:
游戏管理类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public enum GameState
{
Start = 0,
Begin = 1,
Playing = 2,
End = 3,
}
public class EntryManager :MonoBehaviour
{
public GameObject m_StartBtn;
public GameObject m_TryBtn;
public GameObject m_SceneBg1;
public SceneManager m_SceneBg2;
public Bird m_BirdGo;
public Text m_ScoreText;
public GameState m_State = GameState.Start;
private int m_Score = 0;
private static EntryManager m_Instance;
public static EntryManager Instance
{
get
{
return m_Instance;
}
}
public void Start()
{
m_Instance = this;
ToolHelper.SetClicked(m_StartBtn,OnStartClicked);
ToolHelper.SetClicked(m_TryBtn,OnStartClicked);
}
public void GameInit()
{
}
public void AddScore()
{
m_Score = m_Score + 5;
m_ScoreText.text = m_Score.ToString();
}
public void OnStartClicked()
{
m_Score = 0;
m_ScoreText.text = "0";
m_ScoreText.gameObject.SetActive(true);
BeginStart();
}
public void BeginStart()
{
m_BirdGo.BeginGame();
m_StartBtn.gameObject.SetActive(false);
m_TryBtn.gameObject.SetActive(false);
m_SceneBg2.gameObject.SetActive(true);
m_SceneBg2.BeginPlay();
m_SceneBg1.SetActive(false);
m_State = GameState.Playing;
}
public void GameOver()
{
Debug.Log("GameOver");
m_State = GameState.End;
//m_ScoreText.gameObject.SetActive(false);
m_TryBtn.gameObject.SetActive(true);
m_SceneBg2.gameObject.SetActive(false);
m_SceneBg1.SetActive(true);
}
}
飞鸟类:
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Bird : MonoBehaviour
{
public Rigidbody2D m_RigidBody;
public Image m_Sprite;
public int m_Index = 0;
public List<Sprite> m_Sprite1;
public List<Sprite> m_Sprite2;
private List<Sprite> m_CurrentSprite;
public int m_Frame = 0;
public float m_CurSpeed;
public float m_DownAdSpeed;
public float m_UpAdSpeed;
public void Awake()
{
m_CurrentSprite = m_Sprite1;
}
public void BeginGame()
{
transform.localPosition = Vector3.zero;
m_CurSpeed = 0;
}
public void FixedUpdate()
{
++m_Frame;
if (m_Frame >= 5)
{
m_Frame = 0;
m_Index = ++m_Index % m_CurrentSprite.Count;
m_Sprite.sprite = m_CurrentSprite[m_Index];
}
if (transform.localPosition.y >= 520 || transform.localPosition.y <= -400)
{
EntryManager.Instance.GameOver();
}
if (EntryManager.Instance == null)
return;
if (EntryManager.Instance.m_State == GameState.Playing)
{
m_CurSpeed -= m_DownAdSpeed;
if (m_CurSpeed < -6.5f)
{
m_CurSpeed = -6.5f;
}
transform.localPosition += Vector3.up * m_CurSpeed;
}
}
public void Update()
{
if (EntryManager.Instance == null)
return;
if (EntryManager.Instance.m_State == GameState.Playing)
{
if (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0))
{
m_CurSpeed = m_UpAdSpeed;
}
}
}
public void SetBirdImg(int index)
{
if (index == 0)
{
m_CurrentSprite = m_Sprite1;
}
else
{
m_CurrentSprite = m_Sprite2;
}
}
}
场景管理类:
using System.Collections;
using System.Collections.Generic;
//using System.Numerics;
using UnityEngine;
public class SceneManager : MonoBehaviour
{
public SingleScene m_Bg1;
public SingleScene m_Bg2;
public SingleScene m_Bg3;
public float m_ScollSpeed = 10;
//private bool m_IsFirstPass = false;
public float m_LeftBorad = -750;
public void BeginPlay()
{
//m_IsFirstPass = false;
m_Bg1.transform.localPosition = Vector3.zero;
m_Bg2.transform.localPosition = new Vector3(750,0,0);
m_Bg3.transform.localPosition = new Vector3(1500,0,0);
gameObject.SetActive(true);
m_Bg1.ChangeScene();
m_Bg1.ShowGuanzi(false);
m_Bg2.ChangeScene();
m_Bg3.ChangeScene();
}
// Update is called once per frame
void FixedUpdate()
{
if (EntryManager.Instance == null)
return;
if (EntryManager.Instance.m_State == GameState.Playing)
{
float moveDis = m_ScollSpeed;
MoveSingleScene(m_Bg1, moveDis);
MoveSingleScene(m_Bg2, moveDis);
MoveSingleScene(m_Bg3, moveDis);
}
}
private void MoveSingleScene(SingleScene scene,float dis)
{
scene.m_Tf.anchoredPosition += dis * Vector2.left;
if (scene.m_Tf.anchoredPosition.x <= m_LeftBorad)
{
//Debug.Log("Move:" + time);
scene.m_Tf.anchoredPosition = new Vector2(1500, 0);
scene.ChangeScene();
if(scene == m_Bg1)
m_Bg1.ShowGuanzi(true);
}
}
}
这些类一定是要放在一个程序集里进行执行,因为后来是要对程序集进行打包
三。打包Dll
点击菜单:
在对应目录下会生成Dll文件
加个后缀.bytes
放进工程的StreamAsset文件夹下,并且把之前做的入口管理Prefab打成AssetBundle也放进去。
修改官方demo中的loaddll代码。
如图:
最后build测试:
比较顺利,没什么问题。
总结下来:
在整个Demo开发的时候确实没有什么非要注意的潜规则,确实如作者所说几乎0成本接入。后续等如果有机会运用到项目中再说。