using UnityEngine; using UnityEditor; using System.Collections.Generic; using System.IO; public class AnimTitleEditor : EditorWindow { static void SaveTex(Camera camera, string outFile) { var renderTex = camera.RenderToTexture(Screen.width, Screen.height); var tex = new Texture2D(Screen.width, Screen.height, TextureFormat.ARGB32, false); RenderTexture.active = renderTex; tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, false); tex.Apply(); var camTex = new Texture2D(Screen.width / 4, Screen.height / 4, TextureFormat.ARGB32, false); for(int x = 0; x < camTex.width; ++x) { for(int y = 0; y < camTex.height; ++y) { var r = 0f; var g = 0f; var b = 0f; var a = 0f; for(int ox = 0; ox < 4; ++ox) { for(int oy = 0; oy < 4; ++oy) { var pix = tex.GetPixel(x * 4 + ox, y * 4 + oy); r += pix.r; g += pix.g; b += pix.b; a += pix.a; } } var color = new Color(r / 16, g / 16, b / 16, a / 16); camTex.SetPixel(x, y, color); } } GameObject.DestroyImmediate(tex); var alphaColor = new Color(0, 0, 0, 0); var minX = camTex.width; var minY = camTex.height; var maxX = 0; var maxY = 0; for (int x = 0; x < camTex.width; ++x) { for (int y = 0; y < camTex.height; ++y) { var color = camTex.GetPixel(x, y); if (color.r <= 0f && color.g <= 0f && color.b <= 0) { camTex.SetPixel(x, y, alphaColor); } else { if (x - 1 < minX) { minX = x - 1; } if (y - 1 < minY) { minY = y - 1; } if (x + 1 > maxX) { maxX = x + 1; } if (y + 1 > maxY) { maxY = y + 1; } } } } var newTex = new Texture2D(maxX - minX, maxY - minY, TextureFormat.ARGB32, false); for (int x = 0; x < newTex.width; ++x) { for (int y = 0; y < newTex.height; ++y) { newTex.SetPixel(x, y, camTex.GetPixel(x + minX, y + minY)); } } File.WriteAllBytes(outFile, newTex.EncodeToPNG()); camera.targetTexture = null; GameObject.DestroyImmediate(camTex); GameObject.DestroyImmediate(newTex); } [MenuItem("Ares/渲染摄像机家具图片")] static void OutPutCameraJiaJuTexture() { var select = UnityEditor.Selection.activeGameObject; if (select == null) { Debug.LogError("请选择有效的摄像机脚本"); return; } var camera = select.GetComponent(); if (camera == null) { Debug.LogError("请选择有效的摄像机脚本"); return; } var renderPaths = new string[] { "BigWall", "0", //大墙壁,不旋转 "MidWall", "0", //中墙壁,不旋转 "SamWall", "0", //小墙壁,不旋转 "ObjRoot", "1", //场景物件,旋转 }; var rootGo = GameObject.Find("JiaJuRender"); if(rootGo == null) { Debug.LogError("没有找到渲染对象 JiaJuRender Go"); return; } var rootTrans = rootGo.transform; var outPath = EditorUtility.OpenFolderPanel("选择输出目录", "", ""); if (!string.IsNullOrEmpty(outPath)) { for(int k = 0; k < renderPaths.Length / 2; ++k) { var path = renderPaths[k * 2]; var mode = renderPaths[k * 2 + 1]; var trans = rootTrans.Find(path); trans.gameObject.SetActive(true); for (int i = 0; i < trans.transform.childCount; ++i) { for (int j = 0; j < trans.transform.childCount; ++j) { var otherTrans = trans.transform.GetChild(j); otherTrans.gameObject.SetActive(i == j); } var renderTrans = trans.transform.GetChild(i); var forCount = 4; if(mode == "0") { forCount = 1; } for (int index = 0; index < forCount; ++index) { var angles = renderTrans.localEulerAngles; angles.y = index * 90f; renderTrans.localEulerAngles = angles; SaveTex(camera, string.Format("{0}/{1}_{2}.png", outPath, renderTrans.name, index * 90)); } } trans.gameObject.SetActive(false); } } } [MenuItem("Ares/特效称号3转2")] static void Open() { var win = (AnimTitleEditor)EditorWindow.GetWindow(typeof(AnimTitleEditor)); win._isPlaying = false; win.Show(); } private int _texWidth = 256; private int _texHeight = 128; private float _cameraSize = 0.2f; private float _maxTime = 1f; private int _titleIndex = 1; private string _outputPath = string.Empty; private int _frameCount = 10; private float _addAlphaThreshold = 0.7f; private float _addAlphaScale = 0.5f; private bool _isPlaying = false; private GameObject _selectTarget = null; private float _frontUpdateTime = 0f; private float _playTimer = 0f; private Camera _camera = null; private List _texList = new List(); private RenderTexture _targetTexture = null; private Vector3 _goOriPos = Vector3.zero; private int _frontSimple = -1; private Camera _copyCamera = null; private List _copyTexList = new List(); private RenderTexture _copyTargetTexture = null; private GameObject _copyTarget = null; private List _copyMats = new List(); private List _copyTex = new List(); private void OnGUI() { EditorGUILayout.BeginVertical(); if (_isPlaying) { GUILayout.Label("正在渲染"); EditorGUILayout.Slider(_playTimer, 0f, _maxTime); this.Focus(); } else { _texWidth = EditorGUILayout.IntField("图片宽", _texWidth); _texHeight = EditorGUILayout.IntField("图片高", _texHeight); _cameraSize = EditorGUILayout.FloatField("摄像机size", _cameraSize); _maxTime = EditorGUILayout.FloatField("录制时间", _maxTime); _frameCount = EditorGUILayout.IntField("帧率(N帧/秒)", _frameCount); _addAlphaThreshold = EditorGUILayout.FloatField("AddAlpha阀值", _addAlphaThreshold); _addAlphaScale = EditorGUILayout.FloatField("AddAlpha阀值以下缩放", _addAlphaScale); var selectObj = UnityEditor.Selection.gameObjects; if (selectObj != null && selectObj.Length > 0 && _frameCount > 0) { GUILayout.Label(selectObj[0].name); if (GUILayout.Button("开始录制", GUILayout.Width(50))) { StartPlay(selectObj[0]); } } } if (_texList.Count > 0) { _titleIndex = EditorGUILayout.IntField("图片索引", _titleIndex); var rect = new Rect(); rect.size = new Vector2(_texWidth, _texHeight); var count = (int)(this.position.width / (_texWidth + 10)); if (count <= 0) { count = 1; } for (int i = 0; i < _texList.Count; ++i) { rect.position = new Vector2(20 + i % count * (_texWidth + 10), 200 + i / count * (_texHeight + 30)); GUI.Box(rect, _texList[i]); } for (int i = 0; i < _copyTexList.Count; ++i) { int index = i + _texList.Count; rect.position = new Vector2(20 + index % count * (_texWidth + 10), 200 + index / count * (_texHeight + 30)); GUI.Box(rect, _copyTexList[i]); } if (GUILayout.Button("导出", GUILayout.Width(50))) { _outputPath = EditorUtility.OpenFolderPanel("选择输出路径", _outputPath, ""); if (!string.IsNullOrEmpty(_outputPath)) { for (int i = 0; i < _texList.Count; ++i) { MegreAlphaTex(_texList[i], _copyTexList[i]); var bytes = _texList[i].EncodeToPNG(); var path = string.Format("{0}/{1}_{2}.png", _outputPath, _titleIndex, i); File.WriteAllBytes(path, bytes); } } } } EditorGUILayout.EndVertical(); } private void StartPlay(GameObject targetGo) { Stop(); _isPlaying = true; _selectTarget = targetGo; _playTimer = 0f; _goOriPos = _selectTarget.transform.position; _selectTarget.transform.position = new Vector3(0f, 5000f, 0f); var cameraGo = new GameObject("Camera"); cameraGo.transform.position = new Vector3(0f, 5000f, 0f); _camera = cameraGo.RequireComponent(); _camera.clearFlags = CameraClearFlags.SolidColor; _camera.backgroundColor = new Color(0f, 0f, 0f, 1f); _camera.useOcclusionCulling = false; _camera.orthographic = true; _camera.orthographicSize = _cameraSize; _camera.nearClipPlane = -2000; _camera.farClipPlane = 2000; _camera.aspect = (float)_texWidth / _texHeight; _targetTexture = RenderTexture.GetTemporary(_texWidth, _texHeight, 24, RenderTextureFormat.RGB565); _targetTexture.antiAliasing = 1; _camera.targetTexture = _targetTexture; _frontSimple = -1; _selectTarget.SetActive(false); _selectTarget.SetActive(true); for (int i = 0; i < _texList.Count; ++i) { //RenderTexture.ReleaseTemporary(_texList[i]); GameObject.DestroyImmediate(_texList[i]); } _texList.Clear(); _selectTarget.SetActive(false); PlayVfx(_selectTarget); cameraGo = new GameObject("CopyCamera"); cameraGo.transform.position = new Vector3(0f, 10000f, 0f); _copyCamera = cameraGo.RequireComponent(); _copyCamera.clearFlags = CameraClearFlags.SolidColor; _copyCamera.backgroundColor = new Color(0f, 0f, 0f, 1f); _copyCamera.useOcclusionCulling = false; _copyCamera.orthographic = true; _copyCamera.orthographicSize = _cameraSize; _copyCamera.nearClipPlane = -2000; _copyCamera.farClipPlane = 2000; _copyCamera.aspect = (float)_texWidth / _texHeight; _copyTargetTexture = RenderTexture.GetTemporary(_texWidth, _texHeight, 24, RenderTextureFormat.RGB565); _copyTargetTexture.antiAliasing = 1; _copyCamera.targetTexture = _copyTargetTexture; _copyTarget = GameObject.Instantiate(_selectTarget); _copyTarget.transform.parent = _selectTarget.transform.parent; _copyTarget.transform.localScale = _selectTarget.transform.localScale; _copyTarget.transform.position = new Vector3(0f, 10000f, 0f); var renders = _copyTarget.GetComponentsInChildren(); for (int i = 0; i < renders.Length; ++i) { if (renders[i].sharedMaterials != null && renders[i].sharedMaterials.Length > 0) { for (int j = 0; j < renders[i].sharedMaterials.Length; ++j) { var mat = renders[i].materials[j]; var texNames = mat.GetTexturePropertyNames(); var drawModel = 0; var shaderName = mat.shader.name; if (shaderName.Contains("Additive")) { //add模式 drawModel = 1; } else if (shaderName.Contains("AlphaBlend")) { //混合 drawModel = 0; } for (int k = 0; k < texNames.Length; ++k) { var tex = mat.GetTexture(texNames[k]) as Texture2D; if (tex != null) { var haveAlpha = false; var texPath = AssetDatabase.GetAssetPath(tex); var mainIm = AssetImporter.GetAtPath(texPath) as TextureImporter; if (mainIm != null) { mainIm.isReadable = true; AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate); tex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D; haveAlpha = mainIm.DoesSourceTextureHaveAlpha(); } var newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false); newTex.wrapMode = tex.wrapMode; CopyAlphaTex(tex, newTex, drawModel, haveAlpha); mat.SetTexture(texNames[k], newTex); _copyTex.Add(newTex); //mainIm.isReadable = false; //AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate); } } } } } var uitexs = _copyTarget.GetComponentsInChildren(); for (int i = 0; i < uitexs.Length; ++i) { var tex = uitexs[i].mainTexture as Texture2D; if (tex != null) { var haveAlpha = false; var texPath = AssetDatabase.GetAssetPath(tex); var mainIm = AssetImporter.GetAtPath(texPath) as TextureImporter; if (mainIm != null) { mainIm.isReadable = true; AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate); tex = AssetDatabase.LoadAssetAtPath(texPath, typeof(Texture2D)) as Texture2D; haveAlpha = mainIm.DoesSourceTextureHaveAlpha(); } var newTex = new Texture2D(tex.width, tex.height, TextureFormat.ARGB32, false); newTex.wrapMode = tex.wrapMode; uitexs[i].mainTexture = newTex; CopyAlphaTex(tex, newTex, 0, haveAlpha); _copyTex.Add(newTex); //mainIm.isReadable = false; //AssetDatabase.ImportAsset(texPath, ImportAssetOptions.ForceUpdate); } } for (int i = 0; i < _copyTexList.Count; ++i) { //RenderTexture.ReleaseTemporary(_texList[i]); GameObject.DestroyImmediate(_copyTexList[i]); } _copyTexList.Clear(); _frontUpdateTime = Time.realtimeSinceStartup; PlayVfx(_copyTarget); } private void PlayVfx(GameObject go) { go.SetActive(true); var _particles = go.GetComponentsInChildren(); if (_particles != null) { for (int i = 0; i < _particles.Length; ++i) { _particles[i].Play(); } } var _animations = go.GetComponentsInChildren(); if (_animations != null) { for (int i = 0; i < _animations.Length; ++i) { _animations[i].Play(); } } var _animators = go.GetComponentsInChildren(); if (_animators != null) { for (int i = 0; i < _animators.Length; ++i) { AnimatorStateInfo animatorStateInfo = _animators[i].GetCurrentAnimatorStateInfo(0); _animators[i].Play(animatorStateInfo.nameHash); } } } private void CopyAlphaTex(Texture2D src, Texture2D dest, int drawModel, bool haveAlpha) { for (int i = 0; i < src.width; ++i) { for (int j = 0; j < src.height; ++j) { var color = src.GetPixel(i, j); if (drawModel == 0) { //混合 color.r = 1f; color.g = 0f; color.b = 0f; } else if (drawModel == 1) { //Add if (haveAlpha) { if (color.a < _addAlphaThreshold) { color.r = color.a * _addAlphaScale; } else { color.r = 1f; } } else { color.r = (color.r + color.g + color.b) / 3f; } //color.r = 1; color.g = 0f; color.b = 0f; } //color.a = 1f; dest.SetPixel(i, j, color); } } dest.Apply(); } private void MegreAlphaTex(Texture2D colorTex, Texture2D alpha) { for (int i = 0; i < colorTex.width; ++i) { for (int j = 0; j < colorTex.height; ++j) { var color = colorTex.GetPixel(i, j); if (color.r == 0 && color.g == 0 && color.b == 0 && color.a == 1) { color.a = 0f; } else { var colorA = alpha.GetPixel(i, j); color.a = colorA.r; } colorTex.SetPixel(i, j, color); } } colorTex.Apply(); } private void Stop() { _isPlaying = false; //for(int i = 0; i < _texList.Count; ++i) //{ // GameObject.DestroyImmediate(_texList[i]); //} //_texList.Clear(); if (_camera != null) { GameObject.DestroyImmediate(_camera.gameObject); } if (_copyCamera != null) { GameObject.DestroyImmediate(_copyCamera.gameObject); } if (_targetTexture != null) { RenderTexture.ReleaseTemporary(_targetTexture); _targetTexture = null; } if (_copyTargetTexture != null) { RenderTexture.ReleaseTemporary(_copyTargetTexture); _copyTargetTexture = null; } if (_selectTarget != null) { _selectTarget.transform.position = _goOriPos; _selectTarget = null; } if (_copyTarget != null) { GameObject.DestroyImmediate(_copyTarget); _copyTarget = null; } for (int i = 0; i < _copyMats.Count; ++i) { GameObject.DestroyImmediate(_copyMats[i]); } _copyMats.Clear(); for (int i = 0; i < _copyTex.Count; ++i) { GameObject.DestroyImmediate(_copyTex[i]); } _copyTex.Clear(); } //进行采样 private void Simple() { var _oriParts = _selectTarget.GetComponentsInChildren(); var _copyParts = _copyTarget.GetComponentsInChildren(); if (_oriParts != null) { for (int i = 0; i < _oriParts.Length; ++i) { var pats = new ParticleSystem.Particle[_oriParts[i].particleCount]; _oriParts[i].GetParticles(pats); _copyParts[i].SetParticles(pats); } } var tex = new Texture2D(_texWidth, _texHeight, TextureFormat.ARGB32, false); _camera.Render(); RenderTexture.active = _targetTexture; tex.ReadPixels(new Rect(0, 0, _texWidth, _texHeight), 0, 0, false); tex.Apply(); _texList.Add(tex); tex = new Texture2D(_texWidth, _texHeight, TextureFormat.ARGB32, false); _copyCamera.Render(); RenderTexture.active = _copyTargetTexture; tex.ReadPixels(new Rect(0, 0, _texWidth, _texHeight), 0, 0, false); tex.Apply(); _copyTexList.Add(tex); } private void Update() { if (_isPlaying) { float frameTime = 1f / _frameCount; float dt = Time.realtimeSinceStartup - _frontUpdateTime; _frontUpdateTime = Time.realtimeSinceStartup; var curFrame = (int)(_playTimer / frameTime); if (_playTimer > 0f && curFrame > _frontSimple) { _frontSimple = curFrame; Simple(); } _playTimer += dt; if (_playTimer >= _maxTime) { Stop(); } } } }