近期工作遇到的問題及解決方式收藏

Jordan96發表於2018-12-12

第一篇部落格還是要有點乾貨的
工作半年,遇到問題不少,這裡歸總一下:

1.FairyGUI列表動效逐一播放問題

直接上程式碼
註冊列表渲染及點選事件

function DlgWelfare:BindEvent()
    --選項列表
    self.listChooseReward.itemRenderer = function(...) self:itemRenderer_listChooseReward(...) end
end

在上一級點選事件回撥時填充列表item

function DlgWelfare:onClickItem_listChooseType(context)
    --設定動效播放的時候事先設定為不可觸碰(在虛擬列表中,動效播放過程拖動列表會導致index錯亂)
    self.listChooseReward.touchable = false
    --設定初始填數量為0,便於計算不同情況下list的items填充數量
    self.renderItemCount = 0
    self.listChooseReward.numItems = #self.mCurDetail
    local numList = self.listChooseReward.numItems
    --設定播放時間取預計時間和正常列表播放時間的最小值
    self:_PlayAnimation(math.min(self.renderItemCount, numList))
end

在列表填充的時候,每一次填充都會呼叫裡面的方法

---@param obj CompWelfareItem
--“---”註釋是EmmyLua的特定用法
function DlgWelfare:itemRenderer_listChooseReward(index, obj)
    --每次填充list中的item數量都+1
    self.renderItemCount = self.renderItemCount + 1
    local playing = (not self.listChooseReward.touchable)
    --通過obj傳入資料,用obj指向的控制元件寫SetItem方法呼叫傳入的資料
    obj:SetItem(self.mCurDetail[index + 1], playing)
end

呼叫的播放動效

---@param loop number @迴圈次數
function DlgWelfare:_PlayAnimation(loop)
    --播放時列表設定為可見
    self.listChooseReward.visible = true
    --在播放前如果存在計時器,事先把計時器停止再開啟。
    if self.timer then
        self.timer:Stop()
    end
    --動效播放時間為0.15秒
    local duration = 0.15
    local index = 0
    --設定播放計時器
    self.timer = Timer.New(function()
        ---@type CompWelfareItem
        local item = self.listChooseReward:GetChildAt(index)
        item:Play()
        index = index + 1
        if index == loop then
            --當所有的動效播放完成設定列表可點選,保證做其他操作不會受影響
            self.listChooseReward.touchable = true
        end
    end, duration, loop)
    self.timer:Start()
end

調DlgWelfare:itemRenderer_listChooseReward(table, bool)中obj:SetItem(self.mCurDetail[index + 1], playing)傳入的資料

function CompWelfareItem:SetItem(item, playing)
    --lua的用法(true and 0 or 1  返回 0,false and 0 or 1 返回 1),此處是設定控制元件控制器“ctrlApprence”的某個狀態
    self.ctrlApprence.selectedIndex = (playing and 0 or 1)
    self.data = item
end

此處為_PlayAnimation方法中item:Play()

function CompWelfareItem:Play()
    --播放list中item的動效
    self:GetTransition("t0"):Play()
end

當然在最後關閉頁面時需要對某些不在存在的東西進行銷燬

2.關於AB模式FairyGUI渲染問題

在AB模式下圖片不被渲染
在這裡插入圖片描述
在普通模式下則被渲染在這裡插入圖片描述
原因:商城元件下的控制元件背景圖依賴於‘_back_ground’包,商城對於這張圖不直接依賴,在assetbound模式下控制元件所屬的’_public’包不直接載入,三層巢狀導致ab時圖層載入出現mesh的none故障。
解決方法:1.(最優解)將控制元件的背景圖放在’_public’中,釋出即可。
2.新增程式碼
ExUIPackage.AddPackage(’_back_ground’)
主動釋出背景包,公共包提前載入,公共包的引用計數會+1, 這樣就不會在視窗銷燬的時候被釋放掉。這樣可能會導致額外佔用記憶體。

3.關於FairyGUI翻牌效果

Demo中的指令碼是C#寫的

using System;
using System.Collections.Generic;
using FairyGUI;
using DG.Tweening;
using UnityEngine;
public class Card : GButton
{
	GObject _back;
	GObject _front;

	public override void ConstructFromXML(FairyGUI.Utils.XML xml)
	{
		base.ConstructFromXML(xml);

		_back = GetChild("n0");
		_front = GetChild("icon");
		_front.visible = false;
	}
	public bool opened
	{
		get{
		return _front.visible;
		}
		set{
		if (DOTween.IsTweening(this))
				DOTween.Kill(this);

			_front.visible = value;
			_back.visible = !value;
		}
	}
	public void SetPerspective()
	{
		_front.displayObject.perspective = true;
		_back.displayObject.perspective = true;
	}
	public void Turn()
	{
		if (DOTween.IsTweening(this))
			return;

		bool toOpen = !_front.visible;
		DOTween.To(() => 0, x =>
		{
			if (toOpen)
			{
				_back.rotationY = x;
				_front.rotationY = -180 + x;
				if (x > 90)
				{
					_front.visible = true;
					_back.visible = false;
				}
			}
			else
			{
				_back.rotationY = -180 + x;
				_front.rotationY = x;
				if (x > 90)
				{
					_front.visible = false;
					_back.visible = true;
				}
			}
		}, 180, 0.8f).SetTarget(this).SetEase(Ease.OutQuad);
	}
}

using UnityEngine;
using FairyGUI;
using DG.Tweening;
public class TurnCardMain : MonoBehaviour
{
	GComponent _mainView;
	Card _c0;
	Card _c1;
	void Awake()
	{
		Application.targetFrameRate = 60;
		Stage.inst.onKeyDown.Add(OnKeyDown);

		UIPackage.AddPackage("UI/TurnCard");
		UIObjectFactory.SetPackageItemExtension("ui://TurnCard/CardComponent", typeof(Card));
	}

	void Start()
	{
		_mainView = this.GetComponent<UIPanel>().ui;

		_c0 = (Card)_mainView.GetChild("c0");

		_c1 = (Card)_mainView.GetChild("c1");
		_c1.SetPerspective();
		
		_c0.onClick.Add(__clickCard);
		_c1.onClick.Add(__clickCard);
	}

	void __clickCard(EventContext context)
	{
		Card card = (Card)context.sender;
		card.Turn();
	}

	void OnKeyDown(EventContext context)
	{
		if (context.inputEvent.keyCode == KeyCode.Escape)
		{
			Application.Quit();
		}
	}
}

此處為Lua改寫的一些方法

---@class CompCard:GButton@翻牌效果
--註冊控制元件
CompCard = fgui.extension_class(CompBase, 'general', '控制元件_翻牌效果')
function CompCard:SetItem(index)
    self.data = index
end

--繼承CompBase過載ctor函式
function CompCard:ctor()
    --設定反面
    self._back = self:GetChild("n46");
    --設定正面
    self._front = self:GetChild("n47");
    --翻牌前反面向上,正面不顯示
    self._front.visible = false;
    self._front.displayObject.perspective = true;
    self._back.displayObject.perspective = true;
end

翻牌效果函式

function CompCard:Turn()
    local toOpen = not self._front.visible
    --執行dotween動畫播放,旋轉180°,並且設定反面為不可見,正面為可見
    local tween = TweenUtils.TweenFloat(0, 180, 0.8, function(x)
        if (toOpen) then
            self._back.rotationY = x
            self._front.rotationY = -180 + x
            if (x > 90) then
                self._front.visible = true
                self._back.visible = false
            end
        else
            self._back.rotationY = -180 + x
            self._front.rotationY = x
            if (x > 90) then
                self._front.visible = false
                self._back.visible = true
            end

        end
    end)
    TweenUtils.SetTarget(tween, self)
    TweenUtils.SetEase(tween, Ease.OutQuad)
end

需要重新設定屬性

local get = tolua.initget(CompCard)
local set = tolua.initset(CompCard)
get.opened = function(self)
    return self._front.visible
end
set.opened = function(self, value)
    if (TweenUtils.IsTweening(self)) then
        TweenUtils.Kill(self)
        self._front.visible = value
        self._back.visible = not value
    end
end

獲取item再呼叫呼叫翻牌函式

function DlgDupSettlement:onClickItem_listCard(context)
    local item = self.listCard:GetChildAt(index)
    item:Turn(self.getItem)
end

相關文章